Skip to content

ui: PapSignIn, a reactor.ui display for a sign-in waiting for the person - #6

Open
echarles wants to merge 15 commits into
mainfrom
feat/ui-display
Open

echarles wants to merge 15 commits into
mainfrom
feat/ui-display

Conversation

@echarles

Copy link
Copy Markdown
Member

RU-1 (Reactor UI plan), Python slice: the sign-in card's data, typed where PAP lives, so both the gateway and the page depend on the type rather than on a hand-kept shape.

  • personal_agent_protocol.ui.PapSignIn: @display_type("application/vnd.datalayer.pap.sign-in+json", version=1).
    • Fields: mode (direct|device|mediated), open (https only, no userinfo), code (audience("page"), required for device), expires_at and sent_to.
    • text() never contains the code.
  • PapSignIn.from_answer(answer) reads the gateway's pap_sign_in answer and returns None for any status other than waiting_for_the_person. tool_meta() returns {"reactor.ui/display": wire} for an MCP result's _meta.
  • PapCorePlugin.provide_display_types registers the type, importing .ui lazily. Only reactor 1.1 calls that hook, so the SDK still runs on reactor 1.0.x.
  • New extra: ui = ["datalayer_reactor>=1.1.0,<2"]. test_ui.py is skipped (importorskip) until reactor 1.1.0 is on PyPI.

Depends on datalayer/reactor#27 (reactor.ui, 1.1.0). Do not release yet. The gateway's pap_sign_in will return PapSignIn.from_answer(...).tool_meta() once both are released.

Tests: test_ui.py (10) and test_reactor.py, 37 passed locally against the reactor feat/ui-channel checkout.

personal_agent_protocol.ui.PapSignIn (application/vnd.datalayer.pap.sign-in+json,
v1): direct, device or mediated; an https page only; the device code for the
page and never in the model's view; expires_at, sent_to. from_answer reads a
pap_sign_in answer, tool_meta() is the MCP _meta["reactor.ui/display"] that
carries it. The core plugin declares the type via provide_display_types,
importing the module only when a reactor 1.1 asks. New extra: ui
(datalayer_reactor>=1.1.0).
Copilot AI balanced review requested due to automatic review settings October 11, 2026 15:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Device codes embedded in sign-in URLs leak into model-visible fallback text despite the page-only guarantee.

1 open finding
What changed in this PR

Adds a typed Reactor UI sign-in display for PAP workflows, targeting Reactor 1.1.

Changes:

  • Introduces PapSignIn, validation, serialization, and MCP metadata.
  • Registers the display through the Reactor plugin hook.
  • Adds UI tests, dependency extra, and release notes.
File Description
pyproject.toml Adds the Reactor UI dependency extra.
personal_agent_protocol/​ui.py Implements the sign-in display type.
personal_agent_protocol/​reactor.py Registers PAP display types.
personal_agent_protocol/​__tests__/​test_ui.py Tests display behavior and registration.
CHANGELOG.md Documents the new UI integration.

🧠 Review effort: Balanced


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

Comment thread personal_agent_protocol/ui.py Outdated
if self.mode == "direct":
return f"Sign in at {self.host}: open {self.open}, sign in there, and come back."
if self.mode == "device":
return f"Sign in at {self.host}: open {self.open} and enter the code shown there."
…L may carry the code, so open is audience(page) beside code, and the text names only the company's domain; the test checks the complete model view, not the text with the URL stripped (review on #6)
…tor 1.1.0 is released; the test extra requires it), fixing E402 under the pinned ruff
…he overlap, the retired one refused once the cached set expires, unknown kids refetched at most once a minute); the consent page binds its request to the browser (__Host-poppy_consent, a CSRF token from the cookie, consent_decision refusing cross-site, foreign-origin, unbound and replayed forms) and the operation page's form carries a token from its poppy_session cookie, in Python and TypeScript
…orthwind with Ledgerly, every conformance case, the Pydantic AI examples' tools) run with CANARY-minted values and canary passwords; every credential harvested from the wire stays out of logs at DEBUG, raised errors, requested URLs, model-readable bodies, message texts and PapSignIn model views; the npm lib/ embeds no key, token or canary and its browser entry reaches no demo credential. Fixed the leak it found: Ledgerly's connect reply put Northwind's device user code in the message text
…) for replay caches, shared budgets, device polling and SSE fan-out, in Python and TypeScript, with a docs page. Fixed what they found: the memory replay cache never forgot an identifier (it now sweeps expired ones, and the verifiers remember each proof or assertion exactly as long as they would accept it: iat plus the window, exp plus the skew); the shared budget slept under its lock so max_wait never bounded the queue (it now reserves turns, GCRA, refusing a turn beyond max_wait at once, and sleeps again when a timer fires early); check_replay_cache / checkReplayCache and a concurrency option on the store kits
…t the company, the canary suite, load tests and the replay-cache and budget fixes they found)
…rver entry (lib/company/*.js is tsc's unbundled output); API reference regenerated for 0.8.0
…REVISION, OPERATIONS_VERSION in both SDKs, held equal with the docs and packages), aligned Reactor contributions (protocol/reactor-points.json, table-driven lifecycle and tenant tests in both languages; the TypeScript company serves pap.company.mcp; unused profile, extension-handler and key-store points removed; optional points fail closed on ambiguity), every public code example run in CI (docs blocks, Pydantic AI tools, Agent Runtimes PAP apps with agent-runtimes>=1.3.111), compatibility/migration/support pages, signed releases (PyPI attestations, npm provenance)
…datalayer/reactor's own lib/ is not loadable by node: extensionless ESM imports)
…n it asked (the first asks late on a loaded runner, so more callers fit; CI admitted 55 and 28 where the bound ignored that delay)

This branch was successfully deployed

2 active deployments
npm — 81894853 Deployed Oct 11, 2026 by echarles via npm #14
pypi — 81894853 Deployed Oct 11, 2026 by echarles via pypi #14
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.

2 participants