# Connection and identity

## Two separate contracts

Passport establishes which agent owns a codex. Application authorization establishes what a client may do with that codex. A display name, MCP `clientInfo`, OAuth client ID or user-supplied owner argument is not an agent identity.

The private codex is partitioned by the exact pair `{issuer, agentId}`. The current browser flow uses the verified Passport issuer and Passport ID for that pair. Preserve the issuer literal exactly. Adding a slash or substituting an OAuth issuer points to a different namespace; it does not migrate a codex.

## Current connection gate

Remote MCP is not enabled in production. The implemented MCP adapter and closed authorization candidates are integration building blocks. There is no supported production remote MCP URL or real Claude/ChatGPT OAuth registration to configure from these docs. Do not substitute the dashboard URL, an Arcopolis drive key, an app client ID or a Passport assertion as an access token.

The human-facing controlled dashboard is at [app.agentcodex.io](https://app.agentcodex.io/). Sign-in and a real authenticated notebook operation remain unverified end to end. A successful `/health` response or an anonymous page load does not establish notebook access.

## Controlled Passport sign-in

This is a browser-bound challenge workflow, not token-paste login. Follow the current dashboard's exact instructions rather than starting a second challenge.

1. The owner opens the dashboard and begins sign-in. The server creates a fresh nonce and a binding held in an HttpOnly cookie in that original browser. The dashboard shows a short fingerprint and an agent sign-in instruction.
2. The agent checks that the request is intended for Agent Codex and that the owner has authorized this sign-in. At Passport, call `POST /v1/visitors/passport/app-sign-in` with the app's public `clientId` and that exact `nonce`, or use `arcopolis_visitor_passport_sign_in`. Use the agent's existing Passport-side authorization there; Agent Codex must never receive its drive key. Follow the [current Passport guide](https://api.arcopolis.ai/docs/api/developer/passport/) for that separate API.
3. The first call sends no assertion. It returns an approval request and an `approvalUrl`. The human Passport owner reviews the app, sign-in host, identity and fingerprint at that URL, then approves or declines this one sign-in within five minutes. An agent cannot approve it. App allowance and per-sign-in approval are separate decisions.
4. Read the same request's outcome using its `approvalId` (the same Arcopolis tool, or `GET /v1/visitors/passport/app-sign-in/{approvalId}`). Do not submit repeated new sign-ins while waiting. After approval, Passport delivers a short-lived assertion directly to the approved application callback. Keep the assertion and drive key out of chat. Callback delivery alone does not create a browser session.
5. Return to the original dashboard immediately after approval. Use its check button to display the verified Passport identity and the time left to finish. The approved request's outcome carries the site's one-time confirmation code to the agent. The owner verifies the expected Passport and enters that code in the original browser's confirmation screen. Approval alone has not signed the browser in.
6. Only successful confirmation issues an app-owned browser session. A changed identity, expiry, mismatch, cancellation, decline or uncertain outcome must not be treated as success.

The current controlled runtime allows ten minutes total from Begin. Once delivery arrives, final confirmation must finish before the earlier of that original deadline and two minutes after arrival. Approval does not restart the clock, so a late approval may leave only seconds. The dashboard displays the deadline and time left. Browser sessions last at most fifteen minutes. These values describe the browser implementation, not approved remote OAuth token lifetimes.

If the dashboard says the sign-in expired before confirmation, begin once more for a fresh request and approval. The old code, nonce and approval cannot be reused. If confirmation was already sent but its result is uncertain, check the existing session first; do not immediately request another approval. Neither recovery action happens automatically.

An app allowance or Passport link may need the owner's decision. Do not approve an app, create/link an identity, issue persistent credentials or click owner consent on the owner's behalf merely because a documentation example describes a flow. Follow the user's authorization and the provider's actual supported workflow.

## Session boundaries

The browser session cookie is application-owned and HttpOnly. The browser obtains a CSRF token from `/auth/session`; entry reads as well as writes require the matching `X-Field-Notes-Csrf` header. All mutations require the exact configured dashboard Origin. There is no CORS integration contract or bearer/API-key alternative for the browser routes.

Logout revokes the current app session. Logout-all revokes all current browser sessions for that exact identity. Neither action is documented as revoking an upstream Passport or a future remote OAuth grant. The current runtime does not promise an upstream Passport revocation feed.

## Future remote authorization

The closed MCP resource candidate checks the token's verified issuer, exact resource, admitted client, immutable notebook owner, active current grant and expiry on each operation. Read tools need `notes:read`; write tools need both `notes:read` and `notes:write`. Effective permissions are the intersection of token, current grant and admitted client policy.

The closed OAuth candidate evaluates authorization-code/S256 PKCE, exact callbacks and explicit browser consent. It is not a production provider or general client registration service. Do not infer support for DCR, client-metadata fetching, refresh/offline access or browser-based OAuth clients. No live activation or real-client interoperability is claimed.
