feat(turn): recognise a member asking about a trace, ahead of the fetch #347

Merged
coilyco-ops merged 2 commits from feat/recognise-a-trace-lookup-request into main 2026-08-13 10:41:44 +00:00
Member

closes #346

The slice of #339 that lands without a grant. The parent stays open — this does not deliver the fetch.

What it recognises

Both halves required, in both directions:

  • the word trace, on its own word boundary
  • a trace id: 32 hex characters, also on word boundaries

The word alone cannot name a turn, and guessing which one is worse than not answering. An id alone is someone quoting a hash, and reading that as a telemetry request is the false positive the keyword exists to prevent. retrace my steps does not fire.

The id resolves from the message the member replied to as well as from what they typed — the replied-to case is the common one, since the id arrives in a harness notice and the member simply answers it. A typed id wins, because a member who types one has named a different turn from whichever they happen to be replying under. Uppercase resolves: a member pasting from a console is not obliged to preserve the wire's lowercase.

What is deliberately absent

The fetch. No tracing backend is in this service's roster; the grant is deploy-owned and tracked on #278 and coilyco-bridge/deploy#359. A recognised lookup is recorded as turn.trace.requested with served: false, so the demand is measured before the retrieval is built rather than assumed. Member-visible behaviour is unchanged by this PR.

The decision the fetch needs, stated now rather than at implementation time

A trace id is not scoped to whoever pastes it. A member pasting another member's id would be asking this service to read that member's identifiers out in a public channel. Three plausible rules — own-turns-only, anyone-but-summarised, anyone-everything — are written up in docs/sirens-echo-trace-lookup.md. The seam is built toward the narrowest, because a narrow rule can be widened by a decision and a wide one can only be narrowed by an incident.

Coupling

A test asserts the harness's own notice is still parseable by this detector. The two now have to keep agreeing, and a notice shape change should fail in a test rather than quietly in production.

ward exec gate green: build, policy-check, vet, test, test-skips, pre-commit.

closes #346 The slice of https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/339 that lands without a grant. **The parent stays open** — this does not deliver the fetch. ## What it recognises Both halves required, in both directions: - the word `trace`, on its own word boundary - a trace id: 32 hex characters, also on word boundaries The word alone cannot name a turn, and guessing which one is worse than not answering. An id alone is someone quoting a hash, and reading that as a telemetry request is the false positive the keyword exists to prevent. `retrace my steps` does not fire. The id resolves from the message the member **replied to** as well as from what they typed — the replied-to case is the common one, since the id arrives in a harness notice and the member simply answers it. A typed id wins, because a member who types one has named a different turn from whichever they happen to be replying under. Uppercase resolves: a member pasting from a console is not obliged to preserve the wire's lowercase. ## What is deliberately absent The fetch. No tracing backend is in this service's roster; the grant is deploy-owned and tracked on https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/278 and https://forgejo.coilysiren.me/coilyco-bridge/deploy/issues/359. A recognised lookup is recorded as `turn.trace.requested` with `served: false`, so the demand is measured before the retrieval is built rather than assumed. **Member-visible behaviour is unchanged by this PR.** ## The decision the fetch needs, stated now rather than at implementation time A trace id is not scoped to whoever pastes it. A member pasting **another member's** id would be asking this service to read that member's identifiers out in a public channel. Three plausible rules — own-turns-only, anyone-but-summarised, anyone-everything — are written up in `docs/sirens-echo-trace-lookup.md`. The seam is built toward the narrowest, because a narrow rule can be widened by a decision and a wide one can only be narrowed by an incident. ## Coupling A test asserts the harness's own notice is still parseable by this detector. The two now have to keep agreeing, and a notice shape change should fail in a test rather than quietly in production. `ward exec gate` green: build, policy-check, vet, test, test-skips, pre-commit.
feat(turn): recognise a member asking about a trace, ahead of the fetch
All checks were successful
ci / test (pull_request) Successful in 30s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
ci / image-build (pull_request) Successful in 18s
cf5decacc9
A member handed a trace id should be able to ask about it in the channel they
were handed it in. This is the half that needs no grant.

Both halves are required in both directions. The word alone cannot name a
turn, and guessing which one is worse than not answering. An id alone is
someone quoting a hash, and reading that as a telemetry request is the false
positive the keyword exists to prevent.

The id resolves from the message the member replied to as well as from what
they typed, and the replied-to case is the common one, because the id arrives
in a harness notice and the member simply answers it. A typed id wins, since a
member who types an id has named a different turn from whichever they happen
to be replying under. Case is normalised: a member pasting from a console is
not obliged to preserve the lowercase form the wire uses.

The fetch is not here. This service has no tracing backend in its roster, and
that grant is deploy-owned. A recognised lookup is recorded as
turn.trace.requested with served false, so the demand is measured before the
retrieval is built rather than assumed.

The access rule the fetch will need is a decision rather than an
implementation, and it is worth stating before anyone writes it: a trace id is
not scoped to whoever pastes it, so a member pasting another member's id would
be asking this service to read that member's identifiers out in a public
channel. The three plausible rules and the reason to start from the narrowest
are in the doc.

One test asserts the harness's own notice is still parseable by this detector,
because the two now have to keep agreeing and a notice shape change should
fail in a test rather than quietly in production.

closes #346

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilyco-ops force-pushed feat/recognise-a-trace-lookup-request from cf5decacc9
All checks were successful
ci / test (pull_request) Successful in 30s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
ci / image-build (pull_request) Successful in 18s
to 6cb00b8eb5
All checks were successful
ci / test (pull_request) Successful in 29s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
ci / image-build (pull_request) Successful in 18s
2026-08-13 10:40:23 +00:00
Compare
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo!347
No description provided.