You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 3b77f66
Browse filesBrowse the repository at this point in the historyBrowse files
| Customer-owned client credentials | Saved `service_account` credential with a client ID and secret | Internal-app eligibility, grant activation, scope syntax, token lifetime and revocation behavior |
44
+
| API token or personal access token | Saved token service account when reusable connections are useful | Token permissions, identity verification, expiry and rotation |
Do this for every visible OAuth integration. API-key and unauthenticated integrations do not need
278
-
an OAuth client capability.
345
+
Do this for every integration that uses the shared credential picker. Only a connection that
346
+
depends on deployment-wide OAuth client fields needs an OAuth client capability; a customer-owned
347
+
service account must remain available without those fields.
279
348
280
349
The block's `oauth-input.serviceId` is the canonical link between the generated integration catalog,
281
350
the OAuth service configuration, deployment availability, and the setup CLI.
282
351
283
-
1. Ensure the block has exactly one distinct OAuth `serviceId` and that it matches the canonical
284
-
service entry in `apps/sim/lib/oauth/oauth.ts`.
285
-
2. Confirm `resolveOAuthClientCapabilityId(serviceId)` resolves to the intended provider entry in
352
+
1. Set `authMode: AuthMode.OAuth` for integrations using browser OAuth or customer-owned OAuth
353
+
client credentials. Token-only service accounts can retain `AuthMode.ApiKey` with the shared
354
+
picker, as Coda does; `oauth-input` alone does not determine the authentication protocol.
355
+
Register a new token-only service ID and block type in `tokenCredentialIntegrationTypes` in
356
+
`packages/deployment-config/src/integration-availability.ts` so availability and integration
357
+
policy recognize the saved credential path.
358
+
For OAuth integrations, this value lets the catalog discover the connection flow instead of
359
+
routing "Add to Sim" to chat. Ensure the block has exactly one distinct OAuth `serviceId`
360
+
matching the canonical service in `apps/sim/lib/oauth/oauth.ts`. The canonical service's
361
+
`authType` selects browser OAuth or the service-account modal. Verify the resulting catalog
362
+
and block connection actions for the chosen authentication method.
363
+
2. For browser OAuth, confirm `resolveOAuthClientCapabilityId(serviceId)` resolves to the intended provider entry in
286
364
`OAUTH_CLIENT_CAPABILITIES` in `packages/deployment-config/src/env-capabilities.ts`. Google and
287
365
Microsoft service IDs deliberately share provider-level capabilities.
288
-
3. For a new OAuth provider, add the required client fields to `OAUTH_CLIENT_CAPABILITIES`, add
366
+
3. For a new browser OAuth provider, add the required client fields to `OAUTH_CLIENT_CAPABILITIES`, add
289
367
every referenced field to the env schema in `apps/sim/lib/core/config/env.ts`, and add the
290
368
matching `text` or `secret` entries to `OAUTH_CLIENT_SETUP_FIELDS` in
291
369
`packages/sim-setup/src/capability-config.ts`. Do not create integration-specific setup logic or
@@ -298,9 +376,13 @@ the OAuth service configuration, deployment availability, and the setup CLI.
298
376
- no `deploymentRequirement` when the service-account path works independently of OAuth client fields;
299
377
-`'oauth-client'` when it requires the same deployment OAuth client fields;
300
378
-`'preview-gated'` when availability is controlled by the service-account preview block.
379
+
For a service-account-only default, set the canonical service's `authType: 'service_account'`
380
+
and `serviceAccountProviderId`. Verify both block availability and the connect modal with no
381
+
deployment OAuth credentials configured. An existing browser OAuth path may remain for legacy
382
+
credentials without becoming a prerequisite for the new path.
301
383
302
-
Never add a permissive fallback for missing capability metadata. A visible OAuth integration without
303
-
a resolvable capability must fail validation.
384
+
Never add a permissive fallback for missing capability metadata. A browser OAuth connection without
385
+
a resolvable capability must fail validation; an independent service account uses its own metadata.
304
386
305
387
## Step 8: Generate and Validate the Catalog
306
388
@@ -389,7 +471,8 @@ If creating V2 versions (API-aligned outputs):
389
471
-[ ] Set `integrationType` to the correct `IntegrationType` enum value
390
472
-[ ]`{Service}BlockMeta.tags` lists every applicable `IntegrationTag` (tags live on the meta, not the block)
391
473
-[ ] Defined operation dropdown with all operations
392
-
-[ ] Added credential field with `requiredScopes: getScopesForService('{service}')`
474
+
-[ ] Added the saved-credential picker with the supported `credentialKind`; browser OAuth scopes
475
+
use `getScopesForService('{service}')`, while variable service-account permissions stay on the credential
393
476
-[ ] Added conditional fields per operation
394
477
-[ ] Every `short-input`, `long-input`, `code`, and selector subBlock has a `placeholder`
395
478
-[ ] Set up dependsOn for cascading selectors
@@ -407,15 +490,25 @@ If creating V2 versions (API-aligned outputs):
407
490
-[ ]`canvasPresentation.sentences` covers every operation; `bun run apps/sim/scripts/check-canvas-sentences.ts --block={service}` passes
408
491
-[ ]`{Service}BlockMeta` also sets `url` (verified external homepage) and `skills` (grounded in `tools.access`, sourced from real use cases) — see add-block → BlockMeta
-[ ] Chosen app ownership and approval requirements match the intended user
496
+
-[ ] Saved credential picker, tools, and resource selectors share the same provider/region binding
497
+
-[ ] Connect verification, expiry, concurrent workers, secret rotation, and scope changes are sound
498
+
-[ ] Existing usage and the migration/removal decision are established; any required compatibility is verified through serialization and execution
499
+
-[ ] New connection and reconnect flows verified in the running UI
500
+
501
+
### Browser OAuth Scopes (if authorization-code flow is supported)
411
502
-[ ] Defined scopes in `lib/oauth/oauth.ts` under `OAUTH_PROVIDERS`
412
503
-[ ] Added scope descriptions in `SCOPE_DESCRIPTIONS` within `lib/oauth/utils.ts`
413
504
-[ ] Used `getCanonicalScopesForProvider()` in `lib/auth/connectors/providers.ts` (never hardcode)
414
-
-[ ] Used `getScopesForService()` in block `requiredScopes` (never hardcode)
505
+
-[ ] Used `getScopesForService()` for the browser OAuth permissions the block needs (never hardcode)
506
+
-[ ] A picker that also accepts service accounts does not require broader scopes than every supported
507
+
connection needs; per-connection service-account permissions are validated by the descriptor/minter
415
508
416
-
### Deployment Availability (if OAuth service)
509
+
### Deployment Availability (if using the saved-credential picker)
417
510
-[ ] Block declares exactly one distinct `oauth-input.serviceId`
418
-
-[ ]`resolveOAuthClientCapabilityId(serviceId)`resolves to the intended `OAUTH_CLIENT_CAPABILITIES` entry
511
+
-[ ]Browser OAuth resolves to the intended `OAUTH_CLIENT_CAPABILITIES` entry; independent service accounts work without deployment OAuth fields
419
512
-[ ] Every new OAuth capability field exists in `apps/sim/lib/core/config/env.ts`
420
513
-[ ] Runtime OAuth fields live in `OAUTH_CLIENT_CAPABILITIES`; matching CLI input modes live in the exhaustively checked `OAUTH_CLIENT_SETUP_FIELDS`
421
514
-[ ] If `serviceAccountProviderId` is configured, `SERVICE_ACCOUNT_METADATA_BY_OAUTH_SERVICE_ID` has the matching projection and deployment requirement
Copy file name to clipboardExpand all lines: .agents/skills/ship/SKILL.md
+5-2Lines changed: 5 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -47,7 +47,7 @@ When the user runs `/ship`:
47
47
- Run `/db-migrate` to review the migration for zero-downtime safety (expand/contract phasing, backward-compatibility with the deployed app version).
48
48
- `(cd packages/db && bunx drizzle-kit generate && git status --porcelain ./migrations)` must print nothing (CI's schema/migration sync step).
49
49
- `bun run check:migrations origin/staging` must pass (staging is the PR base). Do not silence a flagged statement with a `-- migration-safe:` annotation unless `/db-migrate` confirmed the old code no longer depends on it; otherwise split the destructive change into a later deploy.
50
-
6. **Run pre-ship checks** from the repo root before staging. This has two phases: first **regenerate** every committed artifact so generated files never drift into a CI failure (this is what catches things like `agent-stream-docs` going stale after a `models.ts` edit), then run the **full audit suite** CI's `Lint and Test` job enforces. Both phases parallelize — but only across commands that write **disjoint** outputs — and a bare `wait` swallows child exit codes, so both phases below explicitly collect each job's status and abort ship if any failed.
50
+
6. **Run pre-ship checks** from the repo root before staging. This has two phases: first **regenerate** every committed artifact so generated files never drift into a CI failure (this is what catches things like `agent-stream-docs` going stale after a `models.ts` edit), then run the **full audit suite** CI's `lint` job enforces. Both phases parallelize — but only across commands that write **disjoint** outputs — and a bare `wait` swallows child exit codes, so both phases below explicitly collect each job's status and abort ship if any failed.
51
51
52
52
**Phase A — regenerate the always-in-repo committed artifacts (parallel), then let step 7 stage whatever changed.** Regenerate only the generators whose inputs live entirely in this repo and that any ordinary code change can drift — `agent-stream-docs:generate` (derives from the provider model registry), `docs-manifest:generate` (derives from docs page paths), and `skills:sync` (derives from `.agents/skills/**`). They write disjoint outputs (`apps/docs/…/agent.mdx`, `apps/sim/lib/mothership/generated/docs-manifest.ts`, and `.claude/skills` links), so they parallelize safely, and each is idempotent (a no-op when already in sync):
53
53
```bash
@@ -66,7 +66,7 @@ When the user runs `/ship`:
66
66
67
67
**Do NOT blanket-run the domain generators here.** `mship:generate` (`generate-mship-contracts.ts`) is an **umbrella** that drives all nine mothership contract generators (`mship-contracts`, `billing-protocol-contract`, `mship-tools`, the four `trace-*`, `metrics-contract`, `vfs-snapshot-contract`) and biome-formats `apps/sim/lib/mothership/generated/` — never run it *and* its constituents (they write the same files and corrupt each other in parallel), and never run it on an ordinary ship: it reads an **external** copilot-contract source that isn't checked out in most worktrees, so it hard-fails with `ENOENT` and would abort ship for an unrelated reason. `generate:pi-model-catalog` (under `apps/sim`) likewise regenerates from the installed Pi package, not repo source. `scripts/generate-docs.ts` rewrites the integration docs and client-safe catalog; run it when this PR changes their block/icon/landing-content inputs or when `integration-catalog:check` reports drift, then review its broad generated diff. Only when **this PR's diff actually touches** a domain generator's input do you regenerate it deliberately and run its matching `:check` (`bun run mship:check` / the individual `*:check`) — with the external source present.
68
68
69
-
**Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/test-build.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes:
69
+
**Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/checks.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes:
70
70
```bash
71
71
# autofix formatting first (mutating; not parallel-safe with the audits). Gate its exit too —
72
72
# a non-zero lint (unfixable errors) must abort before the audits run, not be ignored.
@@ -77,6 +77,9 @@ When the user runs `/ship`:
77
77
}
78
78
# Runs every audit CI runs, concurrently, and replays the output of any that fail.
79
79
# The audit list is derived in scripts/run-audits.ts — do not hand-list audits here.
80
+
# Install CI's pinned actionlint version for the host OS/architecture and verify its
81
+
# artifact against the official release checksums in a local mktemp directory.
82
+
# Preserve CI's -shellcheck= -pyflakes= flags; lint all workflows and abort ship if it fails.
80
83
bun run check:audits || { echo"❌ audit(s) failed — do not ship";exit 1; }
81
84
bun run type-check || { echo"❌ type-check failed — do not ship";exit 1; }
82
85
# CI's "Verify docs manifest is in sync" step is not a `check:*` script, so the runner above
0 commit comments