Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a1346b-72a4-7d40-b8bd-8b8ca346cfa2
6.7 KiB
Playwright registration owner contract
Source preparation under NK-WP-0050; live custody, rollout and consumer acceptance remain open. Implements the registration part of RPF-WP-0056 and CUST-WP-0080-T05. The existing browser SecurityCaseType remains unchanged: its HTTPS/standard-scope admission does not cover this loopback/custom-scope use. No case acceptance record is fabricated or borrowed from Forgejo/OpenBao.
Prepare the non-secret records
Run python3 sso-mfa/k8s/keycape/playwright-registration.py for the public
client, or add --agents <identity-references.json> for the complete proposed
Playwright agent inventory. The latter is an array with one object per existing
registered identity:
[
{
"agent_id": "test-agent",
"service_subject": "service:test-agent:platform",
"tenant": "tenant:test",
"identity_record": "synthetic/agent-record.json"
}
]
This example is synthetic; it is not an admitted consumer. The identity owner must confirm each real record, subject, tenant and agent assignment. A reference string is not evidence of registration. Initial eligibility already covers all identified platform humans and coding agents; no new membership decision is needed. The compiler does not provision identities or retrieve/mint credentials.
| Field | Public human client | Each coding agent |
|---|---|---|
| client ID | playwright-cli |
playwright-agent-<agent_id> |
| grant | authorization code, public PKCE | client credentials, confidential |
| audience | playwright-kubernetes |
playwright-kubernetes |
| scope | openid profile groups playwright:connect |
playwright:connect |
| redirect | exact http://127.0.0.1:18764/callback |
none |
| subject/tenant | existing directory user and tenant | exact registered subject/tenant supplied by owner |
| role | existing human roles | only coding-agent |
| lifetime | existing issuer setting, explicit and at most one hour | 15 minutes |
The public client has no per-client lifetime override; KeyCape supports that only for client-credentials clients. Existing issuer lifetime outside the accepted bound refuses preparation and needs owner reconciliation; this tool does not change every client's lifetime. No public tenant override or MFA opt-out is added. The callback, dedicated audience and custom scope match Platform's candidate. The resource uses access tokens; ID tokens retain the client audience.
Each agent gets a distinct proposed env binding from
keycape-<client-id>-client, key client-secret, to
KEYCAPE_<CLIENT_ID_WITH_UNDERSCORES>_CLIENT_SECRET. These names describe a
proposed delivery contract, not existing Secrets or admitted custody. Platform
must bind an exact OpenBao/ESO and consumer delivery route with its own source
task and acceptance. No existing OpenBao client or secret is reused. Secret
values must never enter this identity-reference file, Git, command arguments,
coordination messages or receipts.
Registry and activation boundary
The pure prepare_registry(secret, identities, operation) adapter reuses
keycape-client.py's byte-preserving insertion/removal. It validates the entire
inventory first, refuses differing existing records, ambiguous YAML, duplicate
IDs, shared secret references and unreviewed registrations for this dedicated
audience. An identical registration is a no-op. A separate existing OpenBao
registration for the same agent subject is preserved, with its distinct audience
and secret reference. Unrelated configuration, including signing material, is
unchanged. The encoded result contains private registry data and must stay inside
the protected activation process; the CLI never accepts or emits that registry.
This is not a live apply command. NK-WP-0050-T02 must finish the exact owner activation path using existing registry/Deployment operations:
- Bind verified identity inventory and source digests to the proposal. Obtain the governed per-agent custody and delivery references from Platform.
- Pin current cluster, issuer image and object identities. Read the registry
only within the existing protected owner execution path. Run the actual
pinned KeyCape
check-configon live and proposed configurations, with the exact Deployment env names and policy-store mode; suppress private diagnostics. - Prepare UID/resource-version/data-bound registry mutation and exact env bindings. Preserve all unrelated data and authentication methods. Retain created-only provenance, restart prerequisites, readback and guarded rollback before proposing any live action. A compare-and-swap conflict means reconcile, never replay a stale whole registry.
- Obtain the scoped live action disposition under the existing supervision rules, execute its exact revision, verify config/env/image/readiness and existing human/service login. No new runtime authority comes from this file.
operation=remove is an exact inventory removal proposal, not automatic
rollback: the activation adapter must remove only registrations it created,
preserve pre-existing identical entries and refuse intervening drift. Keep
custody material until recovery/retention requirements are met. Disabling/removing
registration stops new issuance after the issuer loads the change; issued JWTs
remain valid until expiry, and established connections need separate termination
through the transport owner. No immediate global revocation is claimed.
Verification and completion
Python tests exercise preservation, add/no-op/remove, lifetime bounds, identity
conflicts, distinct credentials and contained invalid-input output. The native
Go fixture tests/playwright_registration_native_test.go is copied into a
disposable committed KeyCape checkout at src/internal/authclient/ and consumes
the merged synthetic configuration through PLAYWRIGHT_SYNTHETIC_CONFIG.
It loads the config and domain registrations, performs native token/JWKS
exchanges for both client kinds, and checks dedicated claims, wrong secret,
scope, audience, signature, PKCE and callback refusals. It uses synthetic users
and seeded authorization sessions; it does not prove upstream login, production
image compatibility, native Kubernetes CEL validation or consumer eligibility.
T03 needs actual issuer issuance and native API allow/deny receipts, one real human and one real registered coding agent independently running Platform's consumer command and provider responsive/keyboard trial, renewal, revocation and active connection termination. Cluster authentication and ops-bridge transport remain their owners' implementations. Platform/provider must accept the receipts before managed discovery is published. Same-image abrupt provider recovery is already evidenced; cross-version rollback is still explicitly unproven.