Skip to content

Commit 3b77f66

Browse files
committed
chore(files): align Project backend with current foundation
2 parents 1a6809e + 65f35e1 commit 3b77f66

1,343 files changed

Lines changed: 271233 additions & 18276 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/add-integration/SKILL.md‎

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,79 @@ Before writing any code:
2626
1. Use Context7 to find official documentation: `mcp__context7__resolve-library-id`, then fetch with `mcp__context7__query-docs`
2727
2. Or use WebFetch to read API docs directly
2828
3. Identify:
29-
- Authentication method (OAuth, API Key, both)
29+
- Supported authentication grants, who owns the app, and which permissions each operation needs
3030
- Available operations (CRUD, search, etc.)
3131
- Required vs optional parameters
3232
- Response structures
3333

34+
### Choose the connection flow before building tools
35+
36+
Read the provider's current authentication documentation first. “OAuth” describes a protocol;
37+
it does not imply a browser redirect or a deployment-wide client ID and secret. Compare the
38+
supported paths and choose the simplest supported setup for the intended user:
39+
40+
| Provider method | Sim connection pattern | Verify in the provider docs |
41+
| --- | --- | --- |
42+
| Authorization code | Shared OAuth app and consent flow | Partner approval, redirect URIs, tenant consent, scopes, refresh-token rotation |
43+
| 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 |
45+
| Private key, certificate, or service-account JSON | Existing key-based service-account framework | Signing algorithm, audience, subject, tenant binding and key rotation |
46+
47+
Do not present customer-owned credentials as a way around a provider's approval requirements
48+
for a shared public integration. Explain the supported account/app type in the setup docs. Keep
49+
existing OAuth connections usable when other users depend on them, unless a migration or removal is explicitly authorized.
50+
51+
For client credentials, extend the existing descriptors and minter registry under
52+
`apps/sim/lib/credentials/client-credential-accounts/`; for token credentials, use
53+
`token-service-accounts/`. Reuse the connect modal, encrypted storage, authorized credential
54+
operations, and execution-time token resolver. Do not collect reusable secrets on every block,
55+
invent a credential route, or store a short-lived access token as if it were permanent.
56+
57+
Verify the complete lifecycle, including connect-time verification, concurrent executions on
58+
different workers, expiry, secret rotation, and permission changes. Some providers invalidate the
59+
previous token whenever another is minted. Those providers require shared coordination keyed by
60+
the provider application identity, including across duplicate saved credentials; a process-local
61+
or per-scope token cache is insufficient. A cache hit must never authenticate a wrong secret or
62+
silently grant broader permissions. Bound token responses and retries, prevent credential-bearing
63+
redirects, and never include provider response bodies or secrets in errors.
64+
65+
Use explicit permission choices when the supported operations have different access needs. Keep
66+
region and permission selections on reconnect unless the user changes them. Verify documented
67+
identity endpoints rather than guessing which person a client-credentials token represents.
68+
69+
### Pair saved credentials with block and resource selectors
70+
71+
`oauth-input` is the shared saved-credential picker, including for service accounts that never
72+
redirect to OAuth. Give its basic/advanced pair one `canonicalParamId: 'oauthCredential'`, with
73+
the correct `serviceId`, and wire tool OAuth metadata to that same service. Tokens and trusted
74+
API origins are hidden execution inputs; the model receives a credential ID, never a secret.
75+
Use `credentialKind: 'service-account'` when only service accounts are supported, including in
76+
tool OAuth metadata. Use `credentialKind: 'any'` on the picker when both browser OAuth and saved
77+
service accounts are supported; omitting it defaults the connect action to browser OAuth. Per-connection scope
78+
choices belong in the descriptor and encrypted credential, not an all-permissions block
79+
`requiredScopes` array that would reject read-only connections.
80+
81+
When a documented list endpoint makes a resource ID discoverable, pair the saved credential
82+
with a dynamic resource selector using the `add-selector` and `validate-selector` skills:
83+
84+
- Declare the credential subblock and any parent resource in `dependsOn`, and give the resource
85+
selector and its manual advanced input the same canonical parameter.
86+
- Register browser-safe selector metadata and a server attachment through the shared selector
87+
framework. Resolve the credential with the expected provider binding and use a fixed or
88+
credential-bound destination; selectors and execution must use the same auth/region policy.
89+
- Exercise switching credentials, parent resources, pagination, expired tokens, denied access,
90+
and the advanced environment-reference path. Check that stale choices cannot survive a change
91+
of account. Do not fetch provider data or mint tokens in the browser.
92+
- Keep a manual ID path when the provider cannot enumerate a resource. Do not invent an endpoint
93+
solely to provide a dropdown.
94+
95+
For an existing integration, inspect persisted workflow serialization as well as the visible
96+
form before removing old auth fields. Establish whether existing users need a migration or
97+
compatibility path; do not add permanent legacy branches speculatively when removal is authorized.
98+
When compatibility is needed, prove that old values survive serialization and execution; hiding
99+
a field is not proof. If the user authorizes a production usage check, query only the aggregate usage/auth-shape evidence
100+
needed and keep identities, secrets, and local evidence out of commits and PRs.
101+
34102
### Hard Rule: No Guessed Response Schemas
35103

36104
If the official docs do not clearly show the response JSON shape for an endpoint, you MUST stop and tell the user exactly which outputs are unknown.
@@ -274,18 +342,28 @@ export const TRIGGER_REGISTRY: TriggerRegistry = {
274342

275343
## Step 7: Configure Deployment Availability
276344

277-
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.
279348

280349
The block's `oauth-input.serviceId` is the canonical link between the generated integration catalog,
281350
the OAuth service configuration, deployment availability, and the setup CLI.
282351

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
286364
`OAUTH_CLIENT_CAPABILITIES` in `packages/deployment-config/src/env-capabilities.ts`. Google and
287365
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
289367
every referenced field to the env schema in `apps/sim/lib/core/config/env.ts`, and add the
290368
matching `text` or `secret` entries to `OAUTH_CLIENT_SETUP_FIELDS` in
291369
`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.
298376
- no `deploymentRequirement` when the service-account path works independently of OAuth client fields;
299377
- `'oauth-client'` when it requires the same deployment OAuth client fields;
300378
- `'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.
301383

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.
304386

305387
## Step 8: Generate and Validate the Catalog
306388

@@ -389,7 +471,8 @@ If creating V2 versions (API-aligned outputs):
389471
- [ ] Set `integrationType` to the correct `IntegrationType` enum value
390472
- [ ] `{Service}BlockMeta.tags` lists every applicable `IntegrationTag` (tags live on the meta, not the block)
391473
- [ ] 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
393476
- [ ] Added conditional fields per operation
394477
- [ ] Every `short-input`, `long-input`, `code`, and selector subBlock has a `placeholder`
395478
- [ ] Set up dependsOn for cascading selectors
@@ -407,15 +490,25 @@ If creating V2 versions (API-aligned outputs):
407490
- [ ] `canvasPresentation.sentences` covers every operation; `bun run apps/sim/scripts/check-canvas-sentences.ts --block={service}` passes
408491
- [ ] `{Service}BlockMeta` also sets `url` (verified external homepage) and `skills` (grounded in `tools.access`, sourced from real use cases) — see add-block → BlockMeta
409492

410-
### OAuth Scopes (if OAuth service)
493+
### Authentication and saved credentials
494+
- [ ] Compared documented authorization code, client credentials, token, and key-based methods
495+
- [ ] 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)
411502
- [ ] Defined scopes in `lib/oauth/oauth.ts` under `OAUTH_PROVIDERS`
412503
- [ ] Added scope descriptions in `SCOPE_DESCRIPTIONS` within `lib/oauth/utils.ts`
413504
- [ ] 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
415508

416-
### Deployment Availability (if OAuth service)
509+
### Deployment Availability (if using the saved-credential picker)
417510
- [ ] 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
419512
- [ ] Every new OAuth capability field exists in `apps/sim/lib/core/config/env.ts`
420513
- [ ] Runtime OAuth fields live in `OAUTH_CLIENT_CAPABILITIES`; matching CLI input modes live in the exhaustively checked `OAUTH_CLIENT_SETUP_FIELDS`
421514
- [ ] If `serviceAccountProviderId` is configured, `SERVICE_ACCOUNT_METADATA_BY_OAUTH_SERVICE_ID` has the matching projection and deployment requirement

‎.agents/skills/add-settings-page/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ Each grep lists candidates; review every match against the expected ones named b
6666
- Editable pages: confirm Save/Discard go through `saveDiscardActions()` and
6767
dirty is wired via `useSettingsUnsavedGuard` (called before early-return
6868
gates) — flag any hand-rolled Save button, `beforeunload`, or unsaved modal.
69-
`git grep -n "beforeunload" -- 'apps/sim/**/settings/**' 'apps/sim/ee/'`
70-
should only hit the centralized `use-settings-before-unload.ts`.
69+
`git grep -n "beforeunload" -- 'apps/sim/**/settings/**' 'apps/sim/ee/' 'apps/sim/components/settings/' ':(exclude,glob)**/*.test.*'`
70+
should only hit the centralized `use-settings-browser-navigation.ts`.
7171
5. Fix each finding with the smallest structural change that satisfies the checklist;
7272
do not touch handlers, state, queries, or gate returns. A pixel-size fix swaps
7373
only the size class for its exact-pixel token (`text-[12px]` → `text-caption`).

‎.agents/skills/ship/SKILL.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ When the user runs `/ship`:
4747
- Run `/db-migrate` to review the migration for zero-downtime safety (expand/contract phasing, backward-compatibility with the deployed app version).
4848
- `(cd packages/db && bunx drizzle-kit generate && git status --porcelain ./migrations)` must print nothing (CI's schema/migration sync step).
4949
- `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.
5151
5252
**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):
5353
```bash
@@ -66,7 +66,7 @@ When the user runs `/ship`:
6666
6767
**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.
6868
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:
7070
```bash
7171
# autofix formatting first (mutating; not parallel-safe with the audits). Gate its exit too —
7272
# a non-zero lint (unfixable errors) must abort before the audits run, not be ignored.
@@ -77,6 +77,9 @@ When the user runs `/ship`:
7777
}
7878
# Runs every audit CI runs, concurrently, and replays the output of any that fail.
7979
# 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.
8083
bun run check:audits || { echo "❌ audit(s) failed — do not ship"; exit 1; }
8184
bun run type-check || { echo "❌ type-check failed — do not ship"; exit 1; }
8285
# CI's "Verify docs manifest is in sync" step is not a `check:*` script, so the runner above

0 commit comments

Comments
 (0)