Skip to content

Commit 075b1cd

Browse files
improvement(skills): align application operation guidance (#6532)
1 parent b790a04 commit 075b1cd

14 files changed

Lines changed: 234 additions & 129 deletions

File tree

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -768,9 +768,11 @@ tools: {
768768
}
769769
```
770770

771-
#### 3. Create Internal API Route
771+
#### 3. Create Special Internal Tool Execution Route
772772

773-
Create `apps/sim/app/api/tools/{service}/{action}/route.ts`. Internal tool routes are HTTP boundaries and follow the same contract policy as public routes — define the request/response shape in `apps/sim/lib/api/contracts/tools/{service}.ts` (or an existing aggregate) and validate with canonical helpers from `@/lib/api/server`. Never write a route-local Zod schema.
773+
Create `apps/sim/app/api/tools/{service}/{action}/route.ts`. This raw route pattern is only for an integration's provider-execution boundary when it needs special file normalization, large-body handling, or protocol behavior. It is not the pattern for CRUD or other operations on protected Sim resources. For those, use the `migrate-application-operation` skill and an authorized application use case with the ordinary internal/v2 route builders.
774+
775+
Internal tool routes are HTTP boundaries and follow the same contract policy as public routes — define the request/response shape in `apps/sim/lib/api/contracts/tools/{service}.ts` (or an existing aggregate) and validate with canonical helpers from `@/lib/api/server`. Never write a route-local Zod schema. Authenticate and perform cheap admission before parsing or downloading files.
774776

775777
```typescript
776778
// apps/sim/lib/api/contracts/tools/{service}.ts

.agents/skills/migrate-application-operation/SKILL.md

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
name: migrate-application-operation
3-
description: Migrate one existing Sim resource operation into the shared Principal and application-use-case architecture across internal APIs, public or versioned APIs, Copilot, and other trusted tool adapters. Use when removing route- or tool-local authorization and business logic, consolidating resource reads or writes behind semantic operation policies, or adding another surface to an existing application operation while preserving contracts, identity, errors, rate limits, audit, analytics, and compatibility behavior. Treat v1, uploads, streams, large bodies, bulk recursion, and polymorphic tools as explicitly scoped special cases.
3+
description: Create or migrate a protected Sim resource operation in the shared Principal and application-use-case architecture across internal APIs, public or versioned APIs, Copilot, and other trusted tool adapters. Use when adding a protected endpoint, tool command, or CRUD method; removing route- or tool-local authorization and business logic; consolidating resource reads or writes behind semantic operation policies; or adding another surface to an existing application operation while preserving contracts, identity, errors, rate limits, audit, analytics, and compatibility behavior. Treat v1, uploads, streams, large bodies, bulk recursion, and polymorphic tools as explicitly scoped special cases.
44
---
55

6-
# Migrate Application Operation
6+
# Create Or Migrate Application Operation
77

8-
Migrate one bounded semantic operation at a time. Share authorization and business behavior without forcing internal APIs, public APIs, Copilot, and other tools to share authentication, input schemas, or response shapes.
8+
Create or migrate one bounded semantic operation at a time. Share authorization and business behavior without forcing internal APIs, public APIs, Copilot, and other tools to share authentication, input schemas, or response shapes.
99

1010
## Enforce the application boundary
1111

@@ -43,8 +43,12 @@ Read these files completely before editing:
4343
- `apps/sim/lib/core/application/workspace-operation.ts`
4444
- `apps/sim/lib/core/application/workspace-authorization.ts`
4545
- `apps/sim/lib/core/application/authorized-workspace-use-case.ts`
46+
- `apps/sim/lib/api/server/routes/definition.ts`
4647
- `apps/sim/lib/api/server/routes/internal-json-route.ts`
4748
- `apps/sim/lib/api/server/routes/v2-json-route.ts`
49+
- `apps/sim/lib/auth/internal-delegation.ts`
50+
- `apps/sim/lib/copilot/application/application-adapter.ts`
51+
- `apps/sim/lib/copilot/auth/application-delegation.ts`
4852

4953
Use the file domain only as a representative golden slice:
5054

@@ -116,10 +120,11 @@ rename: defineWorkspaceOperation({
116120
minimumRole: 'write',
117121
workspaceApiKey: 'allow',
118122
principalKinds: ['session', 'personal_api_key', 'workspace_api_key', 'delegated'],
123+
delegatedServices: ['copilot'],
119124
})
120125
```
121126

122-
Do not create internal-, public-, or Copilot-specific versions of the same semantic operation. If two callers have materially different business or transactional semantics, define separate use cases and explain the distinction.
127+
Do not create internal-, public-, or Copilot-specific versions of the same semantic operation. If two callers have materially different business or transactional semantics, define separate semantic operations and use cases and explain the distinction.
123128

124129
Choose principal kinds from actual behavior. Do not accept every principal merely because the use case is shared. Workspace API keys have a write ceiling and cannot satisfy admin operations. The operation definition must fail fast when its role, workspace-key policy, and principal kinds disagree.
125130

@@ -165,17 +170,21 @@ Do not call shared authorization, principal audit attribution, or `recordAudit`
165170

166171
Inspect legacy orchestration before reusing it. If it already authorizes, audits, notifies, or captures analytics, call a lower-level primitive or remove duplicate responsibility for migrated callers.
167172

173+
Application code must remain surface-neutral. It must not import `app/api/**`, `next/server`, internal/v1/v2 contracts or presenters, or Copilot tool handlers. Return domain values and let each surface presenter project its own wire result.
174+
168175
## Adapt internal APIs
169176

170-
Use `defineInternalJsonRoute` for ordinary JSON routes. Explicitly declare the contract, session authentication policy, semantic operation, rate policy, error policy, input mapping, use case, and presenter when the wire result differs.
177+
Use `defineInternalJsonRoute` for ordinary JSON routes. Explicitly declare the contract, authentication policy, semantic operation, rate policy, error policy, input mapping, use case, and presenter when the wire result differs.
178+
179+
Use `internalSessionAuth` for session-only routes. Use `createInternalSessionOrExecutorAuth` only when the endpoint genuinely supports signed executor delegation; the semantic operation must then allow `delegated` principals from the `executor` service. Never turn an actorless legacy JWT into a fake session, owner, or user principal.
171180

172-
The internal adapter owns session authentication and internal response envelopes. It must not implement workspace authorization. Preserve internal-only analytics through `onSuccess` after application success.
181+
The internal adapter owns authentication and internal response envelopes. It must not implement workspace authorization. Preserve internal-only analytics through `onSuccess` after application success.
173182

174183
Keep the route module declarative. If several internal routes repeat authentication, parsing, error rendering, or response construction, improve the shared internal route builder instead of adding a domain-specific route wrapper.
175184

176185
## Adapt public or versioned APIs
177186

178-
Use the appropriate public/versioned route builder, such as `defineV2JsonRoute`, with API-key authentication, explicit operation rate policy, rollout policy, external error projection, and an external presenter.
187+
Use the appropriate public/versioned route builder, such as `defineV2JsonRoute`, with API-key authentication, explicit semantic operation and rate policy, external error projection, input mapping, application use case, and an external presenter. V2 rollout admission is centralized by the builder; do not invent a route-local rollout policy.
179188

180189
Authentication and HTTP formatting may differ from internal APIs; authorization and business behavior must not. Rate-limit using the credential or principal subject, never a billed owner. Resolve billing attribution only for billing, quota, or legacy required-user fields.
181190

@@ -185,7 +194,9 @@ Keep v1 middleware and routes unchanged unless explicitly included.
185194

186195
## Adapt Copilot
187196

188-
Create one domain-level Copilot application adapter instead of constructing delegated principals in every tool:
197+
Copilot is a surface adapter, not a separate application layer. If an HTTP or other surface already uses an application use case, Copilot must call that exact use case rather than reimplementing protected business behavior under `lib/copilot`.
198+
199+
Create one domain-level Copilot application adapter with `createCopilotApplicationAdapter` instead of constructing delegated principals in every tool:
189200

190201
```ts
191202
executeCopilotWidgetUseCase(context, renameWidget, input, { resourceId })
@@ -198,15 +209,16 @@ That adapter must:
198209
- Construct the shared delegated `Principal` in one place.
199210
- Optionally bind the canonical resource scope after trusted resolution.
200211
- Verify that the use case exposes a registered code-defined operation.
212+
- Use the domain's exact immutable operation registry so operation-object membership and identity are checked centrally.
201213
- Call the application use case directly.
202214

203215
Never construct authoritative delegation from model-provided workspace IDs, user IDs, operation IDs, resource scope, or permission tags. Model arguments are requested targets only and must be checked against trusted execution context and canonical data.
204216

205-
Tool handlers own argument aliases, resumable legacy names, abort checks, and tool-specific presentation. They must not query managers directly for protected operations or manually authorize.
217+
Tool handlers own argument aliases, resumable legacy names, abort checks, tool-call reporting, and tool-specific presentation. They must not query managers directly for protected operations, manually authorize, or implement protected business behavior. If a Copilot-only compound action expresses real domain behavior, define a surface-neutral domain operation and application use case for it.
206218

207-
A Copilot reference helper may translate a path to a resource only by calling an authorized application resolver under the intended semantic operation. Passing a code-defined operation object is acceptable; passing a model-provided operation string is not. Reauthorizing during later execution is safe but redundant. When resolution and execution form one business operation, need a consistent snapshot, or appear repeatedly together, prefer a top-level application use case such as `renameWidgetByReference`.
219+
A Copilot reference helper may translate a path to a resource only by calling an authorized application resolver under the intended semantic operation. Passing a code-defined operation object is acceptable; passing a model-provided operation string is not. An immediate same-request resolver followed by the operation may reuse one trusted principal, though the application operation still performs its own canonical authorization. Fresh authentication and authorization are required across lifecycle boundaries such as resumed tool calls, executor callbacks, queued or background work, upload control legs and finalization, durable completion, and long-running provider operations. When resolution and execution form one business operation, need a consistent snapshot, or appear repeatedly together, prefer a top-level application use case such as `renameWidgetByReference`.
208220

209-
Special composition roots may resolve one principal and deliberately thread it through several application calls or lower-level admission stages. Keep this exceptional and explicit; ordinary tools should use the shared execution adapter.
221+
Surface adapters must not compose protected mutations. An atomic compound action requires one top-level semantic domain operation and application use case that owns the transaction and authoritative result. An explicitly best-effort application command may coordinate multiple operations only when it defines hard input and expansion caps, cancellation checkpoints, partial-result semantics, audit behavior, and rate/quota policy. Keep composition exceptional and explicit; ordinary tools should use the shared execution adapter.
210222

211223
Map expected typed errors to safe tool results. Unknown errors must become generic system/retryable messages while retaining full causes in server logs. Never return raw database or storage errors to the model.
212224

@@ -252,10 +264,11 @@ Stop and report a missing design rather than weakening identity, authorization,
252264
Add focused tests for every migrated surface and principal kind allowed by the operation:
253265

254266
- Application: allowed and disallowed roles, principal-kind rejection before canonical loading, workspace assertion mismatch, delegated scope, not found, conflict, no-op, and infrastructure propagation.
267+
- Operation registry: role/workspace-key/principal-kind/delegated-service consistency and fail-fast rejection of invalid definitions.
255268
- Repository: canonical active lookup, workspace-predicated writes, archived resources, authoritative affected rows, and database error propagation.
256269
- Internal API: authentication before parsing, exact contract, typed errors, and surface analytics only after success.
257270
- Public API: personal and workspace keys, rate and rollout behavior, concealment, exact external envelope, and rate headers.
258-
- Copilot or tools: trusted context, rejected forged scope, aliases and resume paths, permission re-check, safe errors, and unchanged tool result shapes.
271+
- Copilot or tools: trusted context, exact registered operation membership, rejected forged scope, aliases and resume paths, permission re-check, safe errors, and unchanged tool result shapes.
259272
- Side effects: audit derives from authoritative results; shared notifications follow audit; neither occurs for rejection or no-op.
260273

261274
Run at minimum:
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
interface:
2-
display_name: "Migrate Application Operation"
3-
short_description: "Share one operation across API and tool surfaces"
4-
default_prompt: "Use $migrate-application-operation to migrate one resource operation across internal APIs, public APIs, Copilot, and other tools."
2+
display_name: "Create Or Migrate Application Operation"
3+
short_description: "Share one protected operation across surfaces"
4+
default_prompt: "Use $migrate-application-operation to create or migrate one protected resource operation across internal APIs, public APIs, Copilot, and other tools."

.claude/commands/add-integration.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -767,9 +767,11 @@ tools: {
767767
}
768768
```
769769

770-
#### 3. Create Internal API Route
770+
#### 3. Create Special Internal Tool Execution Route
771771

772-
Create `apps/sim/app/api/tools/{service}/{action}/route.ts`. Internal tool routes are HTTP boundaries and follow the same contract policy as public routes — define the request/response shape in `apps/sim/lib/api/contracts/tools/{service}.ts` (or an existing aggregate) and validate with canonical helpers from `@/lib/api/server`. Never write a route-local Zod schema.
772+
Create `apps/sim/app/api/tools/{service}/{action}/route.ts`. This raw route pattern is only for an integration's provider-execution boundary when it needs special file normalization, large-body handling, or protocol behavior. It is not the pattern for CRUD or other operations on protected Sim resources. For those, use the `migrate-application-operation` skill and an authorized application use case with the ordinary internal/v2 route builders.
773+
774+
Internal tool routes are HTTP boundaries and follow the same contract policy as public routes — define the request/response shape in `apps/sim/lib/api/contracts/tools/{service}.ts` (or an existing aggregate) and validate with canonical helpers from `@/lib/api/server`. Never write a route-local Zod schema. Authenticate and perform cheap admission before parsing or downloading files.
773775

774776
```typescript
775777
// apps/sim/lib/api/contracts/tools/{service}.ts

0 commit comments

Comments
 (0)