@domino-sdk/relay-cli 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,17 @@
14
14
  ],
15
15
  "evidence": ["tests/auth.test.mjs", "tests/email-auth.test.mjs"]
16
16
  },
17
+ {
18
+ "id": "identity-exchange",
19
+ "support": "native",
20
+ "description": "Keep an existing application login using createParticipantBackend on its server. A Console administrator creates a project/environment identity integration key. The adapter verifies the application session, exchanges its stable subject for a member-only Domino session, and routes participant requests with trusted scope. Keys expire after 90 days and support rotation and revocation.",
21
+ "entrypoints": [],
22
+ "reference": "participant-api",
23
+ "evidence": [
24
+ "tests/identity-integration.test.mjs",
25
+ "apps/api/src/identity-integration.ts"
26
+ ]
27
+ },
17
28
  {
18
29
  "id": "quests",
19
30
  "support": "native",
package/cli/doctor.mjs CHANGED
@@ -182,12 +182,13 @@ export async function diagnose({ project, connection, options }) {
182
182
  id: "remote-access",
183
183
  status: "ok",
184
184
  message:
185
- "Management API verified project access. This does not verify participant sign-in or publication permission.",
185
+ "Management API verified project access. This does not verify participant sign-in or publication permission. Management credentials cannot issue participant sessions. Existing-login integration requires a dedicated server key and createParticipantBackend; run domino capabilities identity-exchange.",
186
186
  });
187
187
  const preflight = await request(connection, "/preflight");
188
188
  readiness = {
189
189
  development: preflight.development,
190
190
  staging: preflight.staging,
191
+ identity: preflight.identity ?? { exchange: "unknown" },
191
192
  };
192
193
  if (project.config.app)
193
194
  checks.push({
@@ -12,8 +12,10 @@ Add the SDK to the package that owns the authored modules using the app's packag
12
12
 
13
13
  For participant UI, inspect the installed `@domino-sdk/relay` and `@domino-sdk/relay/browser` exports. Use the supplied quest controllers for submissions, recovery, and changed rules. Keep stable quest IDs and collection slots. Participants explicitly review changed rules before resubmitting.
14
14
 
15
- Keep the application's existing login. Map its authenticated user through a supported trusted backend identity integration. Determine the server credential and allowed project scope before implementing that exchange. Browser-provided user IDs are not verified identities. Management tokens belong only on trusted servers or in CLI credentials, never browser bundles.
15
+ Keep the application's existing login using `createParticipantBackend` on its server. Read [participant authentication and routing](participant-api.md) for the complete route example. Implement `authenticate(request)` using the app's existing server session verifier and return its stable user ID. Never accept a user ID from browser input as proof of identity.
16
16
 
17
- For same-origin participant routing, inspect `@domino-sdk/relay/portal-proxy` and the app's server route conventions. Its proxy allowlist excludes management routes. Verify session transport, sign-in callbacks where relevant, and a participant action through that boundary. If production identity provisioning is unavailable, report that dependency explicitly and keep the demonstration scoped to test.
17
+ An organization administrator creates an identity integration in Console Settings, under "Use your app's login", for the selected project and environment. The user saves the shown key directly in the application's server secret settings as DOMINO_IDENTITY_KEY. The key is shown once; keep it out of agent chat, source control and browser bundles. CLI and personal management credentials cannot create these keys or substitute for them. Readiness requires the deployed API and SDK versions supporting `identity-exchange`; a legacy 404 is an upgrade issue.
18
+
19
+ Mount the adapter at `/relay/*` and use `createBrowserRelayClient({ baseUrl: "/relay" })`. Verify a signed-in session, one participant action, and that logging out of the application removes access. The adapter checks application authentication on every request and derives project scope from the integration key. No custom fetch wrapper or browser project headers are needed.
18
20
 
19
21
  Read [authoring](authoring.md) when adding quests or collection slots. Run the app's normal checks and development server. Use its existing preview deployment process when available. `domino deploy` publishes Domino behavior; it does not deploy the app. `domino stage` requires a supported Domino-hosted static repository, so it is not a general deployment command for existing apps.
@@ -1,11 +1,47 @@
1
1
  # Participant API
2
2
 
3
- Create `createBrowserRelayClient({ baseUrl: "/relay" })` from `@domino-sdk/relay/browser`. The browser client uses cookies and durable submission recovery. The app's server must route `/relay` through the supported participant proxy. Keep management tokens on the server.
3
+ Create `createBrowserRelayClient({ baseUrl: "/relay" })` from `@domino-sdk/relay/browser`. The browser client uses cookies and durable submission recovery. The app's server must route `/relay` through the supported participant proxy. Management tokens are not participant credentials.
4
4
 
5
5
  ## Sign in
6
6
 
7
7
  Call `relay.auth.providers()` to discover configured providers and email availability. For OAuth, call `relay.auth.start(provider, "sign-in")` and navigate to its returned `url`. For email, call `emailStart(email)`, then `emailVerify(challenge, code)` using the returned challenge. `auth.session()` returns the current session or null. `auth.signOut()` clears the session.
8
8
 
9
+ Email codes and OAuth consent belong to the participant. Let the user complete sign-in in their browser, then verify the resulting session and action. When that has not happened, report sign-in as unverified.
10
+
11
+ ## Existing application login
12
+
13
+ Mount this handler on the application's **server** at `/relay/*`. Use the app's existing session verifier. Its subject must be a stable, non-recycled account ID, not an email or browser-submitted value.
14
+
15
+ ```ts
16
+ import { createParticipantBackend } from "@domino-sdk/relay/portal-proxy";
17
+ import { verifyAppSession } from "./your-existing-server-auth";
18
+
19
+ export const participant = createParticipantBackend({
20
+ baseUrl: "https://relay.domino.run",
21
+ origin: "https://app.example.com",
22
+ integrationKey: process.env.DOMINO_IDENTITY_KEY!,
23
+ authenticate: async (request) => {
24
+ const user = await verifyAppSession(request);
25
+ return user ? { subject: user.id } : null;
26
+ },
27
+ });
28
+ // Wire your framework's GET and POST /relay/* handlers to participant(request).
29
+ ```
30
+
31
+ A Console organization administrator selects the project and environment, opens Settings → Use your app's login, and registers the exact HTTPS application origin. Save the key directly in server secret settings. It is shown once and expires in 90 days. "Replace key" immediately disables the old key while preserving participant identities. "Disconnect" invalidates its sessions too. Recreating an integration creates a new identity namespace; rotate the existing integration to preserve identity continuity.
32
+
33
+ The adapter authenticates the app's session on every request. It exchanges the verified subject using the dedicated integration key, reuses a matching participant session, and keeps its token in a Secure, HttpOnly cookie. Account switching cannot reuse another user's participant session. Application logout removes access on the next request. Use the application's login/logout UI; this adapter does not expose Domino email or OAuth login flows or account linking.
34
+
35
+ The browser still uses `createBrowserRelayClient({ baseUrl: "/relay" })`. Requests must reach the server with the configured HTTPS origin. Mutation requests require the matching Origin and X-Relay-CSRF headers, supplied by the browser client. Never cache these responses.
36
+
37
+ `doctor --remote` checks management and hosting configuration, not the app's session verifier or integration key. Verify `auth.session()`, a participant action, and access after application logout. CLI credentials and personal management tokens are not identity integration keys.
38
+
39
+ ## Server routing and scope
40
+
41
+ The adapter uses `POST /v1/auth/exchange` with `{ subject, previousToken? }` and the integration key as a server bearer credential. Scope and the member role come from the registered integration, never from request input. It adds a server-only integration header when proxying participant requests. A plain exchange result is not a substitute for configuring that routing; use the adapter.
42
+
43
+ `https://console.domino.run/relay` proxies management requests only. Use the participant API origin for the adapter. The lower-level `proxyParticipant` remains available for deployments with preconfigured participant routing; it deliberately excludes browser Authorization and organization/project/environment selectors.
44
+
9
45
  ## Display and complete quests
10
46
 
11
47
  Use `relay.quests.observe(listener)` for the participant's experience. Render the observation's state; dispose the observer when the view unmounts. Read `relay.quests.experience()` for a single snapshot. Open a returned QuestView with `await relay.quests.open(view)`.
@@ -9,3 +9,5 @@ Start with `domino doctor --json`. Add `--remote` to verify project access, publ
9
9
  For compatibility reports, include `domino --version`, `.domino/release.json`, the lockfile, the command and its error. Exclude credentials and private participant data. Install the starter with its frozen lockfile. `release.json` records package versions and archive hashes; matching version strings alone do not establish that locally modified packages match.
10
10
 
11
11
  If development reports unknown catalog fields at `/releases/batch`, the CLI is using an obsolete startup contract. Upgrade to the corrected CLI. Complete deployment bundles belong at `/deployments/preview`, followed by `/deployments/publish` using the returned ID. Do not strip fields from a user's bundle as a permanent workaround.
12
+
13
+ For existing-login failures, read `domino capabilities identity-exchange` and `domino reference participant-api`. Use a dedicated `di_` identity integration key from Console Settings. A 401 means the key or participant session is invalid, expired, revoked, or belongs to another integration. A 400 rejects malformed input, including attempted scope or role overrides. A 429 asks the server to retry later. Older APIs return 404; upgrade the deployment. The Console `/relay` URL remains management-only. The user's application must use the participant API origin through `createParticipantBackend`.
package/dist/index.d.ts CHANGED
@@ -90,6 +90,10 @@ declare const developmentPreflightSchema: z.ZodObject<{
90
90
  test: "test";
91
91
  live: "live";
92
92
  }>;
93
+ identity: z.ZodOptional<z.ZodObject<{
94
+ exchange: z.ZodLiteral<"supported">;
95
+ activeIntegrations: z.ZodNumber;
96
+ }, z.core.$strip>>;
93
97
  staging: z.ZodEnum<{
94
98
  blocked: "blocked";
95
99
  configured: "configured";
package/dist/index.js CHANGED
@@ -120,6 +120,10 @@ var developmentPreflightSchema = z2.object({
120
120
  organization: z2.string(),
121
121
  project: z2.string(),
122
122
  environment: z2.enum(["test", "live"]),
123
+ identity: z2.object({
124
+ exchange: z2.literal("supported"),
125
+ activeIntegrations: z2.number().int().nonnegative()
126
+ }).optional(),
123
127
  staging: z2.enum(["configured", "blocked"]),
124
128
  development: z2.object({
125
129
  status: z2.enum(["configured", "blocked"]),
package/package.json CHANGED
@@ -10,9 +10,9 @@
10
10
  "dependencies": {
11
11
  "commander": "15.0.0",
12
12
  "zod": "4.3.6",
13
- "@domino-sdk/relay": "0.2.0"
13
+ "@domino-sdk/relay": "0.3.0"
14
14
  },
15
- "version": "0.2.0",
15
+ "version": "0.3.0",
16
16
  "bin": {
17
17
  "domino": "./cli.mjs"
18
18
  },