Skip to content

docs(proposals): add real human consent proposal - #298

Open
jpage-godaddy wants to merge 7 commits into
mainfrom
consent-proposal
Open

jpage-godaddy wants to merge 7 commits into
mainfrom
consent-proposal

Conversation

@jpage-godaddy

@jpage-godaddy jpage-godaddy commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Proposes a shared ConfirmationAPI/ConfirmationUI mechanism for guaranteeing real human consent (T&Cs acceptance, purchase confirmation, other high-risk operations) rather than relying on LLM agent prompting alone.
  • Defines the core concepts (ConfirmationRequest, Agreement, ConfirmationSeeker, ConfirmationAPI, ConfirmationUI), their fields, and the separation of OAuth-based agent access from IDP-based human access.
  • Includes diagrams: an actor/interface diagram, a Status lifecycle state diagram, and sequence diagrams for the approval path and the reject/cancel/expire paths.
  • Documents rejected alternatives (OS-level popups, relying on agent prompting).

Refined during review

Copilot's review surfaced several real gaps beyond the initial draft, addressed in this PR:

  • CustomerID/SeekerID must be bound to the caller's authenticated identity, not merely asserted, for both creation and status/cancel calls.
  • Approval must be bound to a specific operation (immutable identifier/digest), and treated as single-use via a mandatory atomic claim - both at approval-consumption time and at request-creation time (idempotent create) - so retries or concurrent pollers can't execute an approved operation twice.
  • Status transitions (including expiry) must be an atomic compare-and-set, not a blind write.
  • TERMS_AND_CONDITIONS agreement data must capture an immutable snapshot/hash of what was accepted, not just a live URL.
  • ConfirmationUI needs a documented read operation, must treat seeker-supplied content as untrusted (XSS), and must have CSRF and clickjacking (framing) protection.
  • The "only direct human interaction" claim is scoped to "IDP-authenticated as the customer" rather than proof of live human presence, which is called out as future work.

Two further refinements on the atomicity/idempotency theme (making the lazy expiry-on-read update itself conditional/atomic, and showing the seeker invoking the atomic claim in the approval flow) were raised in a final review round and are left open for human review rather than folded in automatically - see PR comments.

Test plan

  • Docs-only change; no build/test required
  • Mermaid diagrams render correctly in GitHub's markdown preview

🤖 Generated with Claude Code

Proposes a shared ConfirmationAPI/ConfirmationUI mechanism for
guaranteeing real human consent on high-risk operations (T&Cs,
purchases) that agents cannot satisfy through prompting alone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical and moderate issues remain in authorization, operation binding, state transitions, and consent guarantees.

Review effort: Lite
Findings: 4 High severity · 4 Medium severity · 1 Low severity

Open (9)
What changed in this PR

This docs-only PR proposes a shared human-consent API/UI workflow for high-risk operations.

Changes:

  • Defines confirmation entities, actors, authentication boundaries, and lifecycle states.
  • Documents approval, rejection, cancellation, and expiration flows.
  • Adds Mermaid diagrams and rejected alternatives.
File Description
docs/​proposals/​consent.md Documents the proposed consent model, API contract, UI responsibilities, and workflows.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/proposals/consent.md Outdated
Comment thread docs/proposals/consent.md Outdated
Comment thread docs/proposals/consent.md
Comment thread docs/proposals/consent.md
Comment thread docs/proposals/consent.md
Comment thread docs/proposals/consent.md Outdated
Comment thread docs/proposals/consent.md
Comment thread docs/proposals/consent.md Outdated
Comment thread docs/proposals/consent.md Outdated
Clarifies CustomerID/SeekerID authorization binding, requires atomic
compare-and-set status transitions and lazy expiry enforcement, binds
approval to a specific operation, captures immutable terms snapshots
instead of live URLs, documents ConfirmationUI's read access, and
scopes the human-presence claim to IDP-authenticated identity rather
than proof of live human interaction.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Address the unresolved security, expiration, single-use, and consent-scope concerns.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (9)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Missing CSRF protection on state-changing confirmation requests

docs/​proposals/​consent.md:118

Because ConfirmationUI is an HTML page acting with an IDP-authenticated customer session, a third-party site could forge the approve/reject POST if the session is cookie-based. That would allow a confirmation to be recorded without the customer intentionally interacting with this UI, so the proposal should require CSRF protection (for example, an anti-CSRF token plus Origin/Referer validation, with appropriate cookie settings) on these state-changing calls.

Comment thread docs/proposals/consent.md Outdated
Requires ConfirmationUI to treat seeker-supplied Description/AgreementData
as untrusted (contextual escaping, data-only schema, URL allowlist) and
to protect the approve/reject call with anti-CSRF measures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jpage-godaddy

Copy link
Copy Markdown
Collaborator Author

Fixed in 417eace (addressing the 'Previously missed' CSRF finding, which has no separate review thread to resolve): added a requirement that the approve/reject call be protected with anti-CSRF measures (anti-CSRF token + Origin/Referer validation) so a third-party site can't forge an approval/rejection on the customer's authenticated session.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical authorization and approval-consumption issues, plus an expiration race, block approval.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (1)

Comment thread docs/proposals/consent.md
Comment thread docs/proposals/consent.md
… identity checks

Approval must be treated as single-use/idempotent rather than a durable
signal a seeker can act on repeatedly, and the ConfirmationAPI - not
just the ConfirmationUI's client-side check - must independently
validate the IDP principal against CustomerID on every relevant call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Address the critical expiration race and enforce atomic duplicate-execution protection.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (2)

Comment thread docs/proposals/consent.md Outdated
Comment thread docs/proposals/consent.md Outdated
Fold ExpirationDate into the same compare-and-set predicate as the
status check, closing a race where an approval could read REQUESTED
just before expiry and win the transition just after it. Also
strengthen approval-reuse protection from a recommendation into a
mandatory, atomically-claimed single-execution requirement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved idempotency and atomic audit requirements must be addressed, and the consent terminology should be clarified.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (2)

Comment thread docs/proposals/consent.md
The atomic single-claim mechanism only protects one existing token;
without idempotent creation keyed by the operation identifier, a
retried create call could mint two tokens for the same operation,
each independently approvable and claimable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical security and concurrency requirements remain unresolved.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment thread docs/proposals/consent.md
CSRF tokens don't stop a click induced through an embedded frame;
require CSP frame-ancestors/X-Frame-Options alongside CSRF checks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical atomicity issues and an idempotency-scope issue must be addressed.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (1)

Comment thread docs/proposals/consent.md

**Status** follows a simple lifecycle. `APPROVED`, `REJECTED`, `CANCELLED`, and `EXPIRED` are all terminal; a **ConfirmationRequest** cannot be re-approved, re-rejected, or reopened once it leaves `REQUESTED`.

Each transition out of `REQUESTED` must be applied as an atomic compare-and-set against the persisted status, not a blind write: an approve, reject, or cancel only succeeds if the stored status is still `REQUESTED`, and a request that loses that race receives back whichever terminal status was already recorded. This prevents, for example, an approval and a cancellation racing to overwrite one another. There is no separate "expire" operation in the **ConfirmationAPI**; instead, `ExpirationDate` is part of that same atomic predicate rather than a separate lazy check layered on top - an approve or reject only succeeds if the stored status is `REQUESTED` **and** `ExpirationDate` has not yet passed, evaluated together in the one transition. This closes the race where an approval reads `REQUESTED` just before expiry but would otherwise win the status-only compare-and-set just after it: any transition attempt (or plain read) against a `REQUESTED` request whose `ExpirationDate` has already passed instead persists and returns `EXPIRED`.
Comment thread docs/proposals/consent.md
Seeker->>API: GET /confirmations/{token} (OAuth)
API-->>Seeker: Status
end
Note over Seeker: Status=APPROVED → proceed with operation
@jpage-godaddy

Copy link
Copy Markdown
Collaborator Author

Stopping the automated Copilot review loop here per author decision, after 7 rounds. Six rounds surfaced genuine, progressively-deeper concurrency/security requirements that were fixed (CustomerID/SeekerID authorization binding, operation binding, atomic status transitions, expiry-atomicity, idempotent approval consumption, idempotent creation, clickjacking protection). This final round raised two more in the same vein that are left open for human review rather than auto-fixed:

Both are legitimate refinements of points already in the doc, but the review has reached a point of diminishing, increasingly implementation-level returns for what is meant to be a design proposal rather than a full spec. CI is green (cicd, Analyze, Conventional commit, drift all passing).

@mguerrero3-godaddy mguerrero3-godaddy left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea a lot. Been reading this for a while and wanted to leave some ideas/questions. Most of them out of curiosity but others are related to the design:

  1. This is future-idea but a hook/event handling from cli -> developer portal mobile app could resolve the push notifications. Something similar to claude /remote which gives the notification of an approval needed for an agent on the app.
  2. Security wise I think the expiration is strong, but It'll be good to also consider having a max number of open confirmations, otherwise a really elaborate (but plausible) scenario could spam tons of "similar" confirmations so the human behind can fall in "this kind of looks like It?" and confirm. Similar to MFA spam attacks.
  3. Curious on If reseller or teams account use the cli how would confirmation delegation work in that case or If that's going to be even an option?
  4. Unsure If this could be a valid scenario, but in the case there's several confirmations needed for an action (something requiring T&C and pay in a single go) I see fit a multi-step confirmation where these 'perms' can be checked and then confirmed.
  5. I know the doc is not meant to cover that but curious on If there's a base idea on how the AuditData would be handled? I think some of that is PII
  6. One extending idea (which could be already inferred from the doc) is that a confirmation should be immutable once created and pending (And I think through the whole process), so there's no way to mid-catch and modify It somehow before approval (approving something that changed on the fly)

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.

3 participants