@noodleseed/agent-kit 0.99.1 → 0.101.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.
Files changed (62) hide show
  1. package/manifest.json +373 -373
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +1 -1
  4. package/skills/claude-code/authoring-mcp-servers/SKILL.md +1 -1
  5. package/skills/claude-code/authoring-mcp-servers/references/authoring-workflow.md +21 -2
  6. package/skills/claude-code/authoring-mcp-servers/references/sdk-surface.md +3 -1
  7. package/skills/claude-code/building-mcp-apps/SKILL.md +1 -1
  8. package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
  9. package/skills/claude-code/connecting-apis-to-mcp/references/authoring-workflow.md +21 -2
  10. package/skills/claude-code/creating-product-agent-guides/SKILL.md +1 -1
  11. package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
  12. package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
  13. package/skills/claude-code/deploying-mcp-services/references/cli-commands.md +1 -0
  14. package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
  15. package/skills/claude-code/designing-mcp-products/references/authoring-workflow.md +21 -2
  16. package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
  17. package/skills/claude-code/embedding-mcp-assistants/references/authoring-workflow.md +21 -2
  18. package/skills/claude-code/examples/acme-bistro/README.md +15 -44
  19. package/skills/claude-code/examples/acme-bistro/src/server.ts +66 -11
  20. package/skills/claude-code/examples/acme-bistro/test/server.test.ts +10 -0
  21. package/skills/claude-code/examples/acme-tasks/README.md +11 -11
  22. package/skills/claude-code/examples/gmail-multi-account/README.md +53 -31
  23. package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
  24. package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
  25. package/skills/claude-code/references/authoring-workflow.md +21 -2
  26. package/skills/claude-code/references/cli-commands.md +1 -0
  27. package/skills/claude-code/references/compile-errors.md +4 -1
  28. package/skills/claude-code/references/sdk-surface.md +3 -1
  29. package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
  30. package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
  31. package/skills/claude-code/wrapping-existing-applications/SKILL.md +1 -1
  32. package/skills/claude-code/wrapping-existing-applications/references/authoring-workflow.md +21 -2
  33. package/skills/codex/SKILL.md +1 -1
  34. package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
  35. package/skills/codex/authoring-mcp-servers/references/authoring-workflow.md +21 -2
  36. package/skills/codex/authoring-mcp-servers/references/sdk-surface.md +3 -1
  37. package/skills/codex/building-mcp-apps/SKILL.md +1 -1
  38. package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
  39. package/skills/codex/connecting-apis-to-mcp/references/authoring-workflow.md +21 -2
  40. package/skills/codex/creating-product-agent-guides/SKILL.md +1 -1
  41. package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
  42. package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
  43. package/skills/codex/deploying-mcp-services/references/cli-commands.md +1 -0
  44. package/skills/codex/designing-mcp-products/SKILL.md +1 -1
  45. package/skills/codex/designing-mcp-products/references/authoring-workflow.md +21 -2
  46. package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
  47. package/skills/codex/embedding-mcp-assistants/references/authoring-workflow.md +21 -2
  48. package/skills/codex/examples/acme-bistro/README.md +15 -44
  49. package/skills/codex/examples/acme-bistro/src/server.ts +66 -11
  50. package/skills/codex/examples/acme-bistro/test/server.test.ts +10 -0
  51. package/skills/codex/examples/acme-tasks/README.md +11 -11
  52. package/skills/codex/examples/gmail-multi-account/README.md +53 -31
  53. package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
  54. package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
  55. package/skills/codex/references/authoring-workflow.md +21 -2
  56. package/skills/codex/references/cli-commands.md +1 -0
  57. package/skills/codex/references/compile-errors.md +4 -1
  58. package/skills/codex/references/sdk-surface.md +3 -1
  59. package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
  60. package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
  61. package/skills/codex/wrapping-existing-applications/SKILL.md +1 -1
  62. package/skills/codex/wrapping-existing-applications/references/authoring-workflow.md +21 -2
@@ -3,7 +3,7 @@ name: executing-noodle-plans
3
3
  description: "Use when the user asks to execute an approved, decision-complete implementation plan for a Noodle Seed project task by task with test-first changes, review, recovery, and final verification."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.99.1 hash:6a9f132ddb79352e -->
6
+ <!-- noodle-skill version:0.101.0 hash:6a9f132ddb79352e -->
7
7
 
8
8
  # Execute a Noodle Seed implementation plan
9
9
 
@@ -3,7 +3,7 @@ name: publishing-mcp-integrations
3
3
  description: "Use when preparing, reviewing, or submitting a Noodle Seed MCP integration to a host or app directory."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.99.1 hash:0ccafb222038f553 -->
6
+ <!-- noodle-skill version:0.101.0 hash:0ccafb222038f553 -->
7
7
 
8
8
  # publishing-mcp-integrations
9
9
 
@@ -17,6 +17,7 @@
17
17
  - Tests
18
18
  - Secrets and variables
19
19
  - Embedded assistant
20
+ - Managed collections
20
21
  - Boundaries
21
22
 
22
23
  ## Input paths
@@ -41,9 +42,9 @@ Author in `server.ts`, then `noodle validate` → fix cited errors (see `compile
41
42
 
42
43
  ## Connectors
43
44
 
44
- Declare connectors as data, not imperative code:
45
+ Declare typed connectors:
45
46
 
46
- - **HTTP**: `connector("id").version("1.0.0").http({ baseUrl, allowedOrigins, auth, operations })` with per-operation `request`/`response` mapping using `${args...}` / `${response...}` expressions.
47
+ - **HTTP**: `connector("id").version("1.0.0").http({ baseUrl, allowedOrigins, auth, operations })`; map request/response with `${args...}` / `${response...}`. Use `${execution.id}` for provider idempotency, never model input. Optional `evidence: { outcome: "${response.execution_outcome}", reference: "${response.id}" }` classifies completed/rejected/accepted/unknown; reference is a bounded opaque ID, never a bearer URL or payload. No automatic action retry.
47
48
  - **MCP**: `connector("id").version("1.0.0").mcp({ endpoint, allowedOrigins, auth?, operations })` where each operation freezes the separate upstream `tool` wire name plus input/output schema. Import with `noodle import mcp`; do not hand-copy a live surface or call `tools/list` at runtime.
48
49
  - **Compute**: `connector("id").version("1.0.0").compute(name, { input, output, calls?, run })` — a self-contained, sandboxed function (no imports/closure capture) that may call allowlisted operations via `callOperation`.
49
50
 
@@ -57,6 +58,7 @@ not imported or forwarded. The runtime opens one guarded session for one operati
57
58
  credential, and closes it; it does not act as an agent for upstream sampling, roots, or elicitation.
58
59
 
59
60
  HTTP connector auth variants: `bearer` (`{ kind: "bearer", secret: secret("API_TOKEN") }`), `apiKey` (`{ kind: "apiKey", header: "X-API-Key", secret: secret("API_KEY") }`), `clientCredentials`, `delegatedOAuth`, `delegatedSessionCookie`, and `delegatedTokenExchange` (per-user calls to your own API — see "Delegated downstream auth" below). Use managed `secret(...)` / `variable(...)` refs for all values that differ by org/app/env.
61
+ An application-owned adapter may require its own service credential in addition to the operator account credential. Declare `http.transportAuth: { kind: "apiKey", header: "X-Adapter-Key", secret: secret("ADAPTER_SERVICE_KEY") }` alongside bound account credential profiles; the credential broker supplies the two independently. Never put either credential in tool arguments or ordinary headers, and never reuse an inbound MCP bearer. This capability does not imply a provider requires two credentials.
60
62
 
61
63
  When one connector needs independently selectable accounts, declare catalog `credentialProfiles` plus each operation’s accepted `credentials.profiles`, then bind each `server.use` alias with `bind(connector, { profile, connection: connection("logical_id", managedSecret(secret("NAME"), { scopes, audience })) })`. The alias is the stable account boundary; never put provider account ids, labels, or credential values in it. `gmailConnector()` is the curated Gmail catalog helper; reuse it under independent aliases and accept canonical `accounts` arrays in tools (one account for writes, or an explicitly ordered supported combination for reads). See the bundled `gmail-multi-account` flagship. Bound managed secrets are supported by hosted execution. For deployed-server access to Google APIs, use `googleWorkloadIdentity({ provider: variable("GOOGLE_WIF_PROVIDER"), access: { kind: "direct" } })`, or add `serviceAccountImpersonation` with a managed service-account email. This is keyless Google Workload Identity Federation: exact Google scopes/audience come from the catalog operation, while `noodle auth google prepare|status|doctor|revoke` owns operator lifecycle. See the bundled `google-bigquery` flagship. `externalExchange()` is runnable only when the deployment operator injects an exact HTTPS provider endpoint/origin/audience and durable shared subject-pin store through service ports; Noodle sends a short-lived platform-signed deployment workload assertion and accepts only a bounded bearer response. Provider implementations must consume assertion replay ids through durable shared atomic storage across instances and restarts. There is intentionally no hosted enrollment or provider CRUD surface yet. The provider wire contract is public, but its conformance kit is workspace/source-only and is not an installable npm package. Bound `clientCredentials(...)` remains fail-closed until its provider slice lands.
62
64
 
@@ -407,6 +409,12 @@ Adapt the representative arguments and assertions when business contracts change
407
409
 
408
410
  Author managed config as `secret("NAME")` / `variable("NAME")` and operate it with `noodle secrets set` / `noodle variables set` (scoped org/app/env). Never inline secret values in `server.ts`, tests, or generated files.
409
411
 
412
+ For business-editable configuration, declare `const notice = variable("SERVICE_NOTICE", { schema: z.string().max(500), default: "Welcome", portal: { label: "Service notice", group: "Guest experience" }, requiredFor: ["show_menu"] })` and register it in `server(..., { variables: [notice], ... }, tools)`. Use the same ref in ordinary fulfilment/connector arguments. The default is reusable safe intent; each business supplies its own values without editing source. Only explicit `portal` metadata exposes a setting. Name-only references and declared variables without `portal` remain technical configuration; secrets remain credential slots. See the bundled `acme-bistro` source.
413
+
414
+ Business schemas must be bounded: booleans, finite bounded numbers, bounded text, string enums, bounded arrays, and closed objects. Put defaults in the declaration, not inside Zod schema defaults; custom transforms/refinements and arbitrary schema code cannot run in the shared runtime. `requiredFor` names existing tools whose invocation needs the value; unresolved settings must leave only dependent capabilities unavailable. Publisher compilation does not require a future buyer’s values. Application code enforces business rules server-side; exposing a control or placing the rule in a prompt is insufficient.
415
+
416
+ For an installed application, use the same `noodle variables list|resolve|set|delete` family with `--installation <id> --org <org> --runtime cloud|other`; do not combine it with app/env/scope flags or secrets. Inspection shows schema metadata, provenance, readiness and revision without saved values. Set inputs are JSON (including quotes for strings), read the current projection and save atomically; `--expected-revision <digest>` pins an explicit prior inspection. Delete resets to the current declared default or unset state. Business-administrator permission is required for mutations, conflicts never retry writes, and mutation output excludes values.
417
+
410
418
  ## Embedded assistant
411
419
 
412
420
  To place the same server tools inside a SaaS web app, declare `assistant: embeddedAssistant(...)` alongside the one server-level brand kit. Read `embedded-assistant.md` before integrating: it owns the HTTPS-origin rule, managed model configuration, required deploy-before-client sequence, customer-backend exchange, browser mount, and verification checklist.
@@ -441,6 +449,17 @@ The compiler validates and hashes every document at build time (bad extensions,
441
449
 
442
450
  The managed crawler and managed index are the defaults and need no configuration. A component may instead bring its own crawler (`crawler: firecrawl({ apiKey: secret('FIRECRAWL_API_KEY') })` or `tavily(...)`) and/or its own index (`index: algolia({ appId: variable('ALGOLIA_APP_ID'), apiKey: secret('ALGOLIA_API_KEY') })` or `meilisearch({ host: variable(...), apiKey: secret(...) })`). The code declares only config names; operators supply values with `noodle secrets set` / `noodle variables set`, and deploy preflight fails closed naming any unset reference.
443
451
 
452
+ ## Managed collections
453
+
454
+ Use `managedCollection(name, { title, description, schemaVersion, record })` when an application needs reusable typed intent for business records that Noodle may later hold. Pass it through `server(..., { collections: [...] }, definitions)`. `record` is one bounded, closed Zod object; names use lowercase letters, numbers, and underscores. Keep payment-card, credentials, passport/government identity, health, and biometric fields out of this surface.
455
+ Native record controls are independent: `management: { assignment: true }`, `{ notes: true }`, both, or neither. Status is an ordinary application field such as `progress: z.enum(["received", "reviewing", "handled"]).default("received")`; no framework transition graph exists. Declare `publicFields` explicitly (default empty), `editableFields` for authorized staff (default all schema properties), optional field labels/help, `summaryFields`, `filterFields` and `sortFields`. References must name actual fields and filters/sorts select scalars. Public callers cannot set staff-only fields; a required private field needs a valid creation default. Staff updates merge only admitted fields and revalidate the complete record. See the notes-only `acme-bistro` collection.
456
+ Operator record queries use `noodle solutions records list --filters '[{"field":"progress","value":"received"}]' --sort-field progress`. Only declared scalar equality/sort fields apply. Payload queries scan at most 10,000 candidates; narrow `--created-at-from`/`--created-at-to` if the API returns `query_limit_exceeded`. Ordinary listing/export has no such scan cap. Cursor reuse requires unchanged query/schema and anchor revision. An administrator can explicitly migrate an eligible historical request with `records migrate-schema ... --expected-revision N`; never implement read-time rewrites.
457
+
458
+ Omitting `source` makes Noodle authoritative for the collection. To project a read-only collection from an outside system, bind an HTTP connector in `server(..., { use: [...] })` and add `source: { connector: connector.ref(), scan: "scan_operation" }`. The compiler requires the exact normalized scan contract and the same record schema. Noodle ingests a one-way replica; create, update, and delete in the outside system remain ordinary application tools with their own confirmation and policy.
459
+
460
+ For an explicitly authored native operation, bind `use: { records: noodlePlatform.records.v1 }` and call `connectors.records.submitRecord({ collection: "guest_requests", payload: input })` from an ordinary confirmed tool. Submission accepts only public fields and returns a receipt. `createRecord`, `getRecord`, `listRecords`, `updateRecord`, and `deleteRecord` require a verified platform caller with a live business grant; updates/deletes require the current revision. `updateRecord({ collection, id, expectedRevision, patch, unset: ["optional_field"] })` removes named optional editable fields; omitted keys stay unchanged, `null` is data, and overlap with `patch`, required fields or undeclared fields is rejected. Runtime identity supplies write idempotency and admission; never accept those controls as model arguments. An uninstalled collection is unavailable, including during local tool execution.
461
+ A collection declaration does not create a submit tool, grant access, select retention or residency, provision storage, or expose records to MCP or an embedded assistant. Operators activate the definition and configure lifecycle, access, and any external binding. A connector does not become a collection unless the app explicitly supplies the source contract, and an external collection never becomes a writable mirror.
462
+
444
463
  ## Boundaries
445
464
 
446
465
  Import public app authoring only from `@noodleseed/one` (and its documented `/react` or `/platform` subpaths). Packages and subpaths under `@noodle-borg/*` are runtime implementation details, including `/portable` boundaries, and must never appear in customer `server.ts` code. Do not hand-author manifest JSON/YAML, runtime artifacts, connector IR, or hosted asset metadata. Do not read or copy secrets, bearer tokens, refresh tokens, static access keys, `.env`, `.env.noodle`, or `~/.noodle/config.json`. Hosted access is identity-based — do not add static data-plane credential paths.
@@ -61,6 +61,7 @@ Developer-facing `noodle` commands, grouped by area. Local authoring commands (`
61
61
  | `noodle deployments` | List or inspect individual deployments (`deployments list`/`deployments inspect <id>`). |
62
62
  | `noodle distributions` | Publish immutable host archives, record their lifecycle, and operate bounded delivery. |
63
63
  | `noodle service` | Query hosted service capabilities. |
64
+ | `noodle solutions` | Install managed solutions and operate their grants, records, activity, exports, and deletion. |
64
65
  | `noodle login` | Authenticate with Noodle Seed Cloud. |
65
66
  | `noodle logout` | Clear saved credentials. |
66
67
  | `noodle whoami` | Print the current authenticated user. |
@@ -18,7 +18,7 @@ Run `noodle validate` (add `--json` for the machine-readable envelope, `--fix-pr
18
18
  | `invalid_shape` | A field has the wrong type or structure; match the shape the compiler reports under `path` against the SDK builder you used. |
19
19
  | `invalid_name` | Rename the identifier to match the allowed pattern (lowercase, no spaces/reserved characters) cited at `path`. |
20
20
  | `duplicate_name` | Two tools/components share a name; give each a unique name at the cited `path`. |
21
- | `reserved_name` | Rename the reserved identifier; `__noodleIntent` is platform-owned, while application context uses one explicit zero-input tool with `contextProvider: true`. |
21
+ | `reserved_name` | Rename the reserved identifier; `__noodleIntent` and future managed-collection `submit_<name>` tools are platform-owned, while application context uses one explicit zero-input tool with `contextProvider: true`. |
22
22
  | `unsupported_manifest_version` | Update the SDK/CLI so the emitted manifest version is supported; do not pin an old manifest shape. |
23
23
  | `reserved_for_future_version` | The verb at `path` (currently `compute` as a flow step) is reserved for a future core version; express the step with `use` (a connector operation), `map` (a pure mapping), or the shipped `ctx.elicit` input primitive instead. |
24
24
  | `invalid_operation_ref` | Fix the connector operation reference to `alias.operation` for an operation that exists on that connector. |
@@ -58,6 +58,9 @@ Run `noodle validate` (add `--json` for the machine-readable envelope, `--fix-pr
58
58
  | `state_secret_field` | Remove the secret-shaped field from widget/handle state; secrets must never be stored in state or sent to widgets. |
59
59
  | `invalid_knowledge` | Fix the `knowledge()` declaration: documents must be existing UTF-8 `.md`/`.txt` files inside the project root (no symlinks), within the 100-file / 1 MiB / 25 MiB bounds, and sites need an exact HTTPS origin plus at least one include glob. |
60
60
  | `knowledge_unhashed` | Compile from the project root (`noodle validate`/`noodle dev`) so declared knowledge documents can be read and hashed. |
61
+ | `invalid_managed_collection` | Fix the `managedCollection()` declaration: use a bounded, closed Zod object without credential, payment-card, government-identity, health, or biometric field names. |
62
+ | `invalid_variable_declaration` | Fix the typed `variable()` declaration: use a bounded closed schema, a matching JSON default, plain Portal metadata, existing requiredFor tool names, and one consistent definition per key. |
63
+ | `invalid_managed_collection_source` | Bind the declared source connector and select read-only scan operations whose closed normalized envelopes use the collection record schema exactly. |
61
64
  | `unknown_connector_alias` | The tool calls a connector alias not declared in `use`/`provides`; add it or fix the alias (see `suggestions`). |
62
65
  | `connector_not_in_catalog` | The referenced connector is not in the resolved catalog; add it to the project connectors or correct the reference. |
63
66
  | `unknown_operation` | The connector has no such operation; use an operation declared on that connector (see `didYouMean`/`suggestions`). |
@@ -37,7 +37,7 @@ Platform helper connectors are explicit subpath imports from `@noodleseed/one/pl
37
37
  ### Managed config
38
38
 
39
39
  - `secret("NAME")` — reference a managed secret (operated via `noodle secrets`).
40
- - `variable("NAME")` — reference a managed variable (operated via `noodle variables`).
40
+ - `variable("NAME")` — reference managed configuration; add `{ schema, default?, portal?, requiredFor? }` and register in `server.variables` for typed business settings. Operate through `noodle variables` or authorized Portal settings.
41
41
 
42
42
  ### Customer auth
43
43
 
@@ -63,9 +63,11 @@ Platform helper connectors are explicit subpath imports from `@noodleseed/one/pl
63
63
  - `firecrawl`
64
64
  - `gmailConnector`
65
65
  - `knowledge`
66
+ - `managedCollection`
66
67
  - `managedSecret`
67
68
  - `meilisearch`
68
69
  - `noodleManaged`
70
+ - `noodlePlatform`
69
71
  - `openAICompatible`
70
72
  - `publicWebsite`
71
73
  - `site`
@@ -3,7 +3,7 @@ name: reporting-noodle-feedback
3
3
  description: "Use when a Noodle Seed bug, misleading instruction, missing capability, or concrete product improvement should be proposed to the user."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.99.1 hash:660cc6ad9469d90f -->
6
+ <!-- noodle-skill version:0.101.0 hash:660cc6ad9469d90f -->
7
7
 
8
8
  # reporting-noodle-feedback
9
9
 
@@ -3,7 +3,7 @@ name: verifying-mcp-delivery
3
3
  description: "Use when proving a Noodle Seed MCP project works at a named compile, local, connector, App, host, deployment, or production evidence level."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.99.1 hash:292253cbaed9a3c5 -->
6
+ <!-- noodle-skill version:0.101.0 hash:292253cbaed9a3c5 -->
7
7
 
8
8
  # verifying-mcp-delivery
9
9
 
@@ -3,7 +3,7 @@ name: wrapping-existing-applications
3
3
  description: "Use when an existing application has no stable usable API and needs a read-only, identity-first Noodle Seed integration plan before implementation."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.99.1 hash:379ab9f64878f1fe -->
6
+ <!-- noodle-skill version:0.101.0 hash:379ab9f64878f1fe -->
7
7
 
8
8
  # wrapping-existing-applications
9
9
 
@@ -17,6 +17,7 @@
17
17
  - Tests
18
18
  - Secrets and variables
19
19
  - Embedded assistant
20
+ - Managed collections
20
21
  - Boundaries
21
22
 
22
23
  ## Input paths
@@ -41,9 +42,9 @@ Author in `server.ts`, then `noodle validate` → fix cited errors (see `compile
41
42
 
42
43
  ## Connectors
43
44
 
44
- Declare connectors as data, not imperative code:
45
+ Declare typed connectors:
45
46
 
46
- - **HTTP**: `connector("id").version("1.0.0").http({ baseUrl, allowedOrigins, auth, operations })` with per-operation `request`/`response` mapping using `${args...}` / `${response...}` expressions.
47
+ - **HTTP**: `connector("id").version("1.0.0").http({ baseUrl, allowedOrigins, auth, operations })`; map request/response with `${args...}` / `${response...}`. Use `${execution.id}` for provider idempotency, never model input. Optional `evidence: { outcome: "${response.execution_outcome}", reference: "${response.id}" }` classifies completed/rejected/accepted/unknown; reference is a bounded opaque ID, never a bearer URL or payload. No automatic action retry.
47
48
  - **MCP**: `connector("id").version("1.0.0").mcp({ endpoint, allowedOrigins, auth?, operations })` where each operation freezes the separate upstream `tool` wire name plus input/output schema. Import with `noodle import mcp`; do not hand-copy a live surface or call `tools/list` at runtime.
48
49
  - **Compute**: `connector("id").version("1.0.0").compute(name, { input, output, calls?, run })` — a self-contained, sandboxed function (no imports/closure capture) that may call allowlisted operations via `callOperation`.
49
50
 
@@ -57,6 +58,7 @@ not imported or forwarded. The runtime opens one guarded session for one operati
57
58
  credential, and closes it; it does not act as an agent for upstream sampling, roots, or elicitation.
58
59
 
59
60
  HTTP connector auth variants: `bearer` (`{ kind: "bearer", secret: secret("API_TOKEN") }`), `apiKey` (`{ kind: "apiKey", header: "X-API-Key", secret: secret("API_KEY") }`), `clientCredentials`, `delegatedOAuth`, `delegatedSessionCookie`, and `delegatedTokenExchange` (per-user calls to your own API — see "Delegated downstream auth" below). Use managed `secret(...)` / `variable(...)` refs for all values that differ by org/app/env.
61
+ An application-owned adapter may require its own service credential in addition to the operator account credential. Declare `http.transportAuth: { kind: "apiKey", header: "X-Adapter-Key", secret: secret("ADAPTER_SERVICE_KEY") }` alongside bound account credential profiles; the credential broker supplies the two independently. Never put either credential in tool arguments or ordinary headers, and never reuse an inbound MCP bearer. This capability does not imply a provider requires two credentials.
60
62
 
61
63
  When one connector needs independently selectable accounts, declare catalog `credentialProfiles` plus each operation’s accepted `credentials.profiles`, then bind each `server.use` alias with `bind(connector, { profile, connection: connection("logical_id", managedSecret(secret("NAME"), { scopes, audience })) })`. The alias is the stable account boundary; never put provider account ids, labels, or credential values in it. `gmailConnector()` is the curated Gmail catalog helper; reuse it under independent aliases and accept canonical `accounts` arrays in tools (one account for writes, or an explicitly ordered supported combination for reads). See the bundled `gmail-multi-account` flagship. Bound managed secrets are supported by hosted execution. For deployed-server access to Google APIs, use `googleWorkloadIdentity({ provider: variable("GOOGLE_WIF_PROVIDER"), access: { kind: "direct" } })`, or add `serviceAccountImpersonation` with a managed service-account email. This is keyless Google Workload Identity Federation: exact Google scopes/audience come from the catalog operation, while `noodle auth google prepare|status|doctor|revoke` owns operator lifecycle. See the bundled `google-bigquery` flagship. `externalExchange()` is runnable only when the deployment operator injects an exact HTTPS provider endpoint/origin/audience and durable shared subject-pin store through service ports; Noodle sends a short-lived platform-signed deployment workload assertion and accepts only a bounded bearer response. Provider implementations must consume assertion replay ids through durable shared atomic storage across instances and restarts. There is intentionally no hosted enrollment or provider CRUD surface yet. The provider wire contract is public, but its conformance kit is workspace/source-only and is not an installable npm package. Bound `clientCredentials(...)` remains fail-closed until its provider slice lands.
62
64
 
@@ -407,6 +409,12 @@ Adapt the representative arguments and assertions when business contracts change
407
409
 
408
410
  Author managed config as `secret("NAME")` / `variable("NAME")` and operate it with `noodle secrets set` / `noodle variables set` (scoped org/app/env). Never inline secret values in `server.ts`, tests, or generated files.
409
411
 
412
+ For business-editable configuration, declare `const notice = variable("SERVICE_NOTICE", { schema: z.string().max(500), default: "Welcome", portal: { label: "Service notice", group: "Guest experience" }, requiredFor: ["show_menu"] })` and register it in `server(..., { variables: [notice], ... }, tools)`. Use the same ref in ordinary fulfilment/connector arguments. The default is reusable safe intent; each business supplies its own values without editing source. Only explicit `portal` metadata exposes a setting. Name-only references and declared variables without `portal` remain technical configuration; secrets remain credential slots. See the bundled `acme-bistro` source.
413
+
414
+ Business schemas must be bounded: booleans, finite bounded numbers, bounded text, string enums, bounded arrays, and closed objects. Put defaults in the declaration, not inside Zod schema defaults; custom transforms/refinements and arbitrary schema code cannot run in the shared runtime. `requiredFor` names existing tools whose invocation needs the value; unresolved settings must leave only dependent capabilities unavailable. Publisher compilation does not require a future buyer’s values. Application code enforces business rules server-side; exposing a control or placing the rule in a prompt is insufficient.
415
+
416
+ For an installed application, use the same `noodle variables list|resolve|set|delete` family with `--installation <id> --org <org> --runtime cloud|other`; do not combine it with app/env/scope flags or secrets. Inspection shows schema metadata, provenance, readiness and revision without saved values. Set inputs are JSON (including quotes for strings), read the current projection and save atomically; `--expected-revision <digest>` pins an explicit prior inspection. Delete resets to the current declared default or unset state. Business-administrator permission is required for mutations, conflicts never retry writes, and mutation output excludes values.
417
+
410
418
  ## Embedded assistant
411
419
 
412
420
  To place the same server tools inside a SaaS web app, declare `assistant: embeddedAssistant(...)` alongside the one server-level brand kit. Read `embedded-assistant.md` before integrating: it owns the HTTPS-origin rule, managed model configuration, required deploy-before-client sequence, customer-backend exchange, browser mount, and verification checklist.
@@ -441,6 +449,17 @@ The compiler validates and hashes every document at build time (bad extensions,
441
449
 
442
450
  The managed crawler and managed index are the defaults and need no configuration. A component may instead bring its own crawler (`crawler: firecrawl({ apiKey: secret('FIRECRAWL_API_KEY') })` or `tavily(...)`) and/or its own index (`index: algolia({ appId: variable('ALGOLIA_APP_ID'), apiKey: secret('ALGOLIA_API_KEY') })` or `meilisearch({ host: variable(...), apiKey: secret(...) })`). The code declares only config names; operators supply values with `noodle secrets set` / `noodle variables set`, and deploy preflight fails closed naming any unset reference.
443
451
 
452
+ ## Managed collections
453
+
454
+ Use `managedCollection(name, { title, description, schemaVersion, record })` when an application needs reusable typed intent for business records that Noodle may later hold. Pass it through `server(..., { collections: [...] }, definitions)`. `record` is one bounded, closed Zod object; names use lowercase letters, numbers, and underscores. Keep payment-card, credentials, passport/government identity, health, and biometric fields out of this surface.
455
+ Native record controls are independent: `management: { assignment: true }`, `{ notes: true }`, both, or neither. Status is an ordinary application field such as `progress: z.enum(["received", "reviewing", "handled"]).default("received")`; no framework transition graph exists. Declare `publicFields` explicitly (default empty), `editableFields` for authorized staff (default all schema properties), optional field labels/help, `summaryFields`, `filterFields` and `sortFields`. References must name actual fields and filters/sorts select scalars. Public callers cannot set staff-only fields; a required private field needs a valid creation default. Staff updates merge only admitted fields and revalidate the complete record. See the notes-only `acme-bistro` collection.
456
+ Operator record queries use `noodle solutions records list --filters '[{"field":"progress","value":"received"}]' --sort-field progress`. Only declared scalar equality/sort fields apply. Payload queries scan at most 10,000 candidates; narrow `--created-at-from`/`--created-at-to` if the API returns `query_limit_exceeded`. Ordinary listing/export has no such scan cap. Cursor reuse requires unchanged query/schema and anchor revision. An administrator can explicitly migrate an eligible historical request with `records migrate-schema ... --expected-revision N`; never implement read-time rewrites.
457
+
458
+ Omitting `source` makes Noodle authoritative for the collection. To project a read-only collection from an outside system, bind an HTTP connector in `server(..., { use: [...] })` and add `source: { connector: connector.ref(), scan: "scan_operation" }`. The compiler requires the exact normalized scan contract and the same record schema. Noodle ingests a one-way replica; create, update, and delete in the outside system remain ordinary application tools with their own confirmation and policy.
459
+
460
+ For an explicitly authored native operation, bind `use: { records: noodlePlatform.records.v1 }` and call `connectors.records.submitRecord({ collection: "guest_requests", payload: input })` from an ordinary confirmed tool. Submission accepts only public fields and returns a receipt. `createRecord`, `getRecord`, `listRecords`, `updateRecord`, and `deleteRecord` require a verified platform caller with a live business grant; updates/deletes require the current revision. `updateRecord({ collection, id, expectedRevision, patch, unset: ["optional_field"] })` removes named optional editable fields; omitted keys stay unchanged, `null` is data, and overlap with `patch`, required fields or undeclared fields is rejected. Runtime identity supplies write idempotency and admission; never accept those controls as model arguments. An uninstalled collection is unavailable, including during local tool execution.
461
+ A collection declaration does not create a submit tool, grant access, select retention or residency, provision storage, or expose records to MCP or an embedded assistant. Operators activate the definition and configure lifecycle, access, and any external binding. A connector does not become a collection unless the app explicitly supplies the source contract, and an external collection never becomes a writable mirror.
462
+
444
463
  ## Boundaries
445
464
 
446
465
  Import public app authoring only from `@noodleseed/one` (and its documented `/react` or `/platform` subpaths). Packages and subpaths under `@noodle-borg/*` are runtime implementation details, including `/portable` boundaries, and must never appear in customer `server.ts` code. Do not hand-author manifest JSON/YAML, runtime artifacts, connector IR, or hosted asset metadata. Do not read or copy secrets, bearer tokens, refresh tokens, static access keys, `.env`, `.env.noodle`, or `~/.noodle/config.json`. Hosted access is identity-based — do not add static data-plane credential paths.