Skip to content

Record the agreed human-presence mechanism for analysis summaries - #260

Merged
adamjohnwright merged 1 commit into
mainfrom
docs/011-human-presence-agreed
Sep 19, 2026
Merged

adamjohnwright merged 1 commit into
mainfrom
docs/011-human-presence-agreed

Conversation

@adamjohnwright

Copy link
Copy Markdown
Contributor

Settles FR-013 with the website session, and unblocks spec 011 Phase 8.

Presence rides as claims on the caller token they already mint, set only when their Turnstile-backed identity cookie validated: human (absent rather than false, so a missing claim and a failed check are indistinguishable to us), human_iat for freshness, and subject — a random 16-byte value — for per-person throttling.

Freshness is 30 minutes, enforced at both ends. They refuse to mint past it; we refuse to accept past it. Neither side is a single point of failure. The claim's lifetime is deliberately shorter than the token's, because an HMAC cookie is a bearer credential and a long-lived presence claim is a durable bot pass with extra steps.

The proposal that was withdrawn, and why it matters

They first proposed gating on the analysis token instead: running an analysis is real work already done, so the token is decent evidence somebody meant it. Sound for abuse resistance, wrong for this requirement — which is about consent, not cost.

A token proves an analysis happened. It does not prove a person is present, nor that the person present is the one who ran it. Analysis tokens travel in URLs that people paste into tickets and papers, so token-as-authorization lets a forwarded link send someone else's identifier list to a model provider.

The sharper point is second-order: FR-011 and FR-012 make summarising opt-in with a choice of disclosure tier. A choice a bot holding a link can make is a consent mechanism that consents on the user's behalf — worse than offering no choice, because it looks like one.

Tasks

T031 done. T031a (the 30-minute bound), T031b (limiter keyed on subject, plus a per-token limit) and T031c (a stale human_iat refused with zero model calls) are the work it implies. T031c exists because the freshness half is the one most likely to be dropped: the claim being present looks like success.

One external dependency remains and it is theirs — their proxy mints caller tokens for the answer route only, so a summary route must exist before any claim can be carried. Everything in Phase 8 can be built and tested first.

Documentation only; no code changes.

🤖 Generated with Claude Code

…cked

The website session and I settled FR-013. Presence rides as claims on the
caller token they already mint, set only when their Turnstile-backed identity
cookie validated on the request: `human` (absent rather than false, so a
missing claim and a failed check look the same to us), `human_iat` for
freshness, and `subject`, a random 16-byte value, for per-person throttling.

Freshness is 30 minutes and both sides enforce it -- they refuse to mint past
it, we refuse to accept past it -- so neither is a single point of failure. The
claim's lifetime is deliberately shorter than the token's, because an HMAC
cookie is a bearer credential and a long-lived presence claim is a durable bot
pass with extra steps.

They first proposed gating on the analysis token instead, on the grounds that
running an analysis is real work already done and so decent evidence somebody
meant it. That is sound for abuse resistance and wrong for this requirement,
which is about consent. A token proves an analysis happened, not that a person
is present, and not that the person present is the one who ran it -- analysis
tokens travel in URLs people paste into tickets and papers. Worse, FR-011 and
FR-012 make summarising opt-in with a choice of disclosure tier, and a choice a
bot holding a forwarded link can make is a consent mechanism that consents on
the user's behalf. That is worse than offering no choice, because it looks like
one. They agreed and withdrew it.

Their rate-limiting caveat is adopted as its own task: per token and per
caller regardless, because a token asking for twenty summaries of one analysis
is not a scientist. It is a throttle, not evidence of a person.

T031 is done. T031a-c are the work it implies. One external dependency remains
and it is theirs: their proxy mints caller tokens for the answer route only, so
a summary route must exist before any claim can be carried. Nothing here
assumes the browser calls us directly -- it cannot, the cookie is same-site to
their origin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@adamjohnwright
adamjohnwright force-pushed the docs/011-human-presence-agreed branch from f56fbcf to 1b7930b Compare September 19, 2026 03:49
@adamjohnwright
adamjohnwright merged commit cbabaab into main Sep 19, 2026
10 checks passed
@adamjohnwright
adamjohnwright deleted the docs/011-human-presence-agreed branch September 19, 2026 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant