@jr2/orchestrator 0.6.0 → 0.7.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.
- package/console/components/app.ts +55 -15
- package/console/components/bottom-drawer.ts +259 -0
- package/console/components/drawer.ts +14 -6
- package/console/components/fleet.ts +36 -13
- package/console/components/machine-pane.ts +61 -5
- package/console/components/nav.ts +54 -8
- package/console/conversation.ts +161 -0
- package/console/login.ts +123 -0
- package/console/main.ts +600 -60
- package/console/store.ts +611 -64
- package/console/style.css +231 -0
- package/docs/agents-block.md +2 -2
- package/docs/concepts/agents-and-turns.md +86 -9
- package/docs/concepts/architecture.md +41 -28
- package/docs/concepts/callers-and-hooks.md +205 -0
- package/docs/concepts/charts.md +7 -5
- package/docs/concepts/composition.md +10 -1
- package/docs/concepts/converge.md +4 -2
- package/docs/concepts/durable-runs.md +43 -16
- package/docs/concepts/effects.md +50 -22
- package/docs/concepts/gates.md +95 -25
- package/docs/concepts/machines-and-workflows.md +5 -4
- package/docs/concepts/pools-and-sources.md +187 -11
- package/docs/concepts/secrets-and-trust.md +73 -33
- package/docs/concepts/the-menu.md +11 -0
- package/docs/concepts/workspaces.md +6 -5
- package/docs/get-started/a-model-decides.md +14 -13
- package/docs/get-started/an-agent-in-a-sandbox.md +43 -34
- package/docs/get-started/connect-a-model.md +1 -1
- package/docs/get-started/create-an-instance.md +17 -14
- package/docs/guides/add-tools-to-the-sandbox.md +55 -11
- package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
- package/docs/guides/answer-a-gate.md +74 -37
- package/docs/guides/bind-open-parts.md +24 -8
- package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
- package/docs/guides/cancel-a-run.md +26 -16
- package/docs/guides/fix-a-failed-converge.md +18 -6
- package/docs/guides/give-a-caller-a-scope.md +203 -0
- package/docs/guides/give-an-agent-mcp-tools.md +422 -0
- package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
- package/docs/guides/let-an-agent-write-a-chart.md +9 -6
- package/docs/guides/look-inside-a-sandbox.md +101 -31
- package/docs/guides/open-the-console.md +63 -14
- package/docs/guides/read-a-conversation.md +225 -0
- package/docs/guides/run-a-chart-by-name.md +17 -16
- package/docs/guides/run-one-worker-per-item.md +15 -9
- package/docs/guides/set-an-agents-access-and-dials.md +2 -0
- package/docs/guides/start-a-run-for-each-alert.md +290 -0
- package/docs/guides/start-a-run-from-a-run.md +18 -16
- package/docs/guides/start-a-run.md +24 -18
- package/docs/guides/steer-an-agent.md +332 -0
- package/docs/guides/use-a-hosted-provider.md +1 -1
- package/docs/guides/watch-a-run.md +127 -121
- package/docs/guides/write-a-hook-kind.md +238 -0
- package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
- package/docs/guides/write-a-workflow.md +17 -7
- package/docs/llms.txt +81 -15
- package/docs/reference/authoring-surface/agent.md +1 -1
- package/docs/reference/authoring-surface/answer.md +1 -1
- package/docs/reference/authoring-surface/arg.md +1 -1
- package/docs/reference/authoring-surface/basic.md +1 -1
- package/docs/reference/authoring-surface/bearer.md +1 -1
- package/docs/reference/authoring-surface/branchname.md +1 -1
- package/docs/reference/authoring-surface/carry.md +23 -0
- package/docs/reference/authoring-surface/chartschema.md +1 -1
- package/docs/reference/authoring-surface/chartschemafor.md +1 -1
- package/docs/reference/authoring-surface/command.md +1 -1
- package/docs/reference/authoring-surface/customize.md +4 -1
- package/docs/reference/authoring-surface/defineconfig.md +1 -1
- package/docs/reference/authoring-surface/defineevent.md +1 -1
- package/docs/reference/authoring-surface/dispatch.md +5 -4
- package/docs/reference/authoring-surface/fail.md +1 -1
- package/docs/reference/authoring-surface/file.md +1 -1
- package/docs/reference/authoring-surface/frompick.md +1 -1
- package/docs/reference/authoring-surface/gate.md +118 -0
- package/docs/reference/authoring-surface/group-agents.md +15 -0
- package/docs/reference/authoring-surface/group-charts.md +16 -0
- package/docs/reference/authoring-surface/group-composition.md +25 -0
- package/docs/reference/authoring-surface/group-config.md +17 -0
- package/docs/reference/authoring-surface/group-effects.md +48 -0
- package/docs/reference/authoring-surface/group-failure.md +13 -0
- package/docs/reference/authoring-surface/group-gates.md +16 -0
- package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
- package/docs/reference/authoring-surface/group-steering.md +12 -0
- package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
- package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
- package/docs/reference/authoring-surface/http.md +1 -1
- package/docs/reference/authoring-surface/isfailure.md +1 -1
- package/docs/reference/authoring-surface/isready.md +1 -1
- package/docs/reference/authoring-surface/jr2setup.md +13 -3
- package/docs/reference/authoring-surface/mcp.md +107 -0
- package/docs/reference/authoring-surface/open.md +5 -3
- package/docs/reference/authoring-surface/openbody.md +1 -1
- package/docs/reference/authoring-surface/paramsof.md +1 -1
- package/docs/reference/authoring-surface/pool.md +77 -9
- package/docs/reference/authoring-surface/push.md +1 -1
- package/docs/reference/authoring-surface/readyof.md +1 -1
- package/docs/reference/authoring-surface/reread.md +19 -0
- package/docs/reference/authoring-surface/secret.md +1 -1
- package/docs/reference/authoring-surface/sentby.md +1 -1
- package/docs/reference/authoring-surface/skip.md +22 -0
- package/docs/reference/authoring-surface/source.md +56 -1
- package/docs/reference/authoring-surface/steer.md +93 -0
- package/docs/reference/authoring-surface/text.md +1 -1
- package/docs/reference/authoring-surface/type-agentdefinition.md +14 -1
- package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
- package/docs/reference/authoring-surface/type-anyframepath.md +1 -1
- package/docs/reference/authoring-surface/type-anyworktreepath.md +1 -1
- package/docs/reference/authoring-surface/type-binding.md +1 -1
- package/docs/reference/authoring-surface/type-caller.md +40 -0
- package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
- package/docs/reference/authoring-surface/type-carry.md +19 -0
- package/docs/reference/authoring-surface/type-chainlink.md +3 -3
- package/docs/reference/authoring-surface/type-commandoutput.md +1 -1
- package/docs/reference/authoring-surface/type-customize.md +16 -1
- package/docs/reference/authoring-surface/type-delivered.md +17 -0
- package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
- package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
- package/docs/reference/authoring-surface/type-dispatchoutput.md +1 -1
- package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
- package/docs/reference/authoring-surface/type-framepath.md +1 -1
- package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
- package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
- package/docs/reference/authoring-surface/type-gatelook.md +37 -0
- package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
- package/docs/reference/authoring-surface/type-gatereply.md +19 -0
- package/docs/reference/authoring-surface/type-gateslot.md +21 -0
- package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
- package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
- package/docs/reference/authoring-surface/type-gateslots.md +12 -0
- package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +1 -1
- package/docs/reference/authoring-surface/type-httpoutput.md +1 -1
- package/docs/reference/authoring-surface/type-jr2config.md +37 -2
- package/docs/reference/authoring-surface/type-lateroutcome.md +1 -1
- package/docs/reference/authoring-surface/type-lends.md +5 -1
- package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
- package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
- package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
- package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
- package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
- package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
- package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
- package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
- package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
- package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
- package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
- package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
- package/docs/reference/authoring-surface/type-poolnextinput.md +1 -1
- package/docs/reference/authoring-surface/type-poolspec.md +11 -6
- package/docs/reference/authoring-surface/type-pushoutput.md +1 -1
- package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
- package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
- package/docs/reference/authoring-surface/type-reposlot.md +1 -1
- package/docs/reference/authoring-surface/type-reread.md +18 -0
- package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
- package/docs/reference/authoring-surface/type-sender.md +26 -1
- package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
- package/docs/reference/authoring-surface/type-size.md +1 -1
- package/docs/reference/authoring-surface/type-skip.md +19 -0
- package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
- package/docs/reference/authoring-surface/type-sourcein.md +25 -0
- package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
- package/docs/reference/authoring-surface/type-sourcespec.md +16 -7
- package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
- package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
- package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
- package/docs/reference/authoring-surface/type-steerargs.md +20 -0
- package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
- package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
- package/docs/reference/authoring-surface/type-workspaced.md +1 -1
- package/docs/reference/authoring-surface/type-worktreefound.md +3 -3
- package/docs/reference/authoring-surface/type-worktreeinput.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeoptions.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeoutput.md +1 -1
- package/docs/reference/authoring-surface/type-worktreepath.md +1 -1
- package/docs/reference/authoring-surface/type-worktreeready.md +1 -1
- package/docs/reference/authoring-surface/type-worktreerefused.md +4 -4
- package/docs/reference/authoring-surface/workspace.md +1 -1
- package/docs/reference/authoring-surface/worktree.md +1 -1
- package/docs/reference/authoring-surface.md +88 -167
- package/docs/reference/cli.md +413 -74
- package/docs/reference/config.md +235 -2
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +71 -11
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +14 -10
- package/docs/reference/decisions/0006-agent-control-surface.md +4 -4
- package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
- package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
- package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
- package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
- package/docs/reference/decisions/0012-workspace-wrapper-machine.md +9 -2
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +20 -14
- package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
- package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +18 -14
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -12
- package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
- package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +32 -18
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +14 -1
- package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
- package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +116 -34
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +38 -37
- package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
- package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +7 -6
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +23 -7
- package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
- package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
- package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -18
- package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
- package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +4 -3
- package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
- package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +5 -4
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +19 -19
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
- package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
- package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
- package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +7 -0
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +13 -7
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +38 -30
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +64 -17
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +2 -1
- package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
- package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +51 -23
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +94 -54
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +101 -47
- package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
- package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +17 -13
- package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
- package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
- package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +4 -3
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +37 -10
- package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
- package/docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md +198 -0
- package/docs/reference/decisions.md +6 -4
- package/docs/reference/glossary.md +96 -42
- package/docs/reference/hooks.md +1077 -0
- package/docs/reference/http-api.md +976 -149
- package/docs/why.md +2 -1
- package/package.json +10 -3
- package/src/actor.ts +36 -10
- package/src/agent.ts +50 -0
- package/src/assembly-checks.ts +530 -4
- package/src/callers.ts +245 -0
- package/src/chart.ts +52 -7
- package/src/config.ts +550 -1
- package/src/conversations.ts +453 -0
- package/src/custodian.ts +8 -2
- package/src/customize.ts +143 -4
- package/src/dispatch-effect.ts +142 -26
- package/src/durability.ts +2 -0
- package/src/duration.ts +20 -0
- package/src/effect-checks.ts +2 -1
- package/src/effect.ts +60 -7
- package/src/effector-wire.ts +272 -27
- package/src/gate-brand.ts +16 -0
- package/src/gate.ts +634 -48
- package/src/harness-client.ts +10 -4
- package/src/held-secrets.ts +72 -23
- package/src/holds.ts +2 -2
- package/src/hook-kinds/discord.ts +92 -0
- package/src/hook-kinds/door.ts +107 -0
- package/src/hook-kinds/github.ts +89 -0
- package/src/hook-kinds/gitlab.ts +72 -0
- package/src/hook-kinds/hook.ts +7 -0
- package/src/hook-kinds/index.ts +465 -0
- package/src/hook-kinds/slack.ts +151 -0
- package/src/hook-kinds/webhook.ts +113 -0
- package/src/hooks.ts +506 -0
- package/src/http-effect.ts +76 -38
- package/src/http.ts +889 -94
- package/src/index.ts +16 -5
- package/src/instance.ts +196 -26
- package/src/internal.ts +22 -3
- package/src/machine-doc.ts +26 -1
- package/src/mcp-effect.ts +424 -0
- package/src/mount-digest.ts +41 -7
- package/src/names.ts +64 -2
- package/src/notices.ts +138 -10
- package/src/open-body.ts +25 -11
- package/src/open-effect.ts +17 -4
- package/src/open.ts +4 -2
- package/src/parts.ts +87 -9
- package/src/party.ts +2 -1
- package/src/pick.ts +2 -2
- package/src/pool.ts +1142 -163
- package/src/registration.ts +203 -13
- package/src/run-host.ts +1509 -171
- package/src/run-list.ts +191 -0
- package/src/sandbox-kube.ts +53 -5
- package/src/secret-placement.ts +239 -33
- package/src/server.ts +53 -4
- package/src/setup.ts +72 -32
- package/src/snapshot-store.ts +565 -48
- package/src/steer.ts +111 -0
- package/src/stub-harness.ts +6 -2
- package/src/tokens.ts +263 -22
- package/src/wire.ts +17 -0
- package/src/workspace.ts +50 -6
- package/src/worktree.ts +3 -3
- package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
|
@@ -313,9 +313,18 @@ refusals of a push and of the [Effector](../reference/glossary.md#effector) imag
|
|
|
313
313
|
A check can fail when the model works, for example a model that loads for longer than the check waits. When you know
|
|
314
314
|
that the models work, run `jr2 up --skip-provider-preflight`. No check pod runs, and the converge goes on. `jr2 up`
|
|
315
315
|
writes one line:
|
|
316
|
-
`warning: provider: preflight skipped (--skip-provider-preflight) — these models were not checked: <model>, …`.
|
|
317
|
-
|
|
318
|
-
|
|
316
|
+
`warning: provider: preflight skipped (--skip-provider-preflight) — these models were not checked: <model>, …`. When
|
|
317
|
+
an Agent names a remote MCP server, the line ends with
|
|
318
|
+
`; these MCP servers' tool lists were not checked: <server>, …`. A model that does not work then fails in a run, as
|
|
319
|
+
`agent.fault`, and not at the converge. Remove the flag when the check works again.
|
|
320
|
+
|
|
321
|
+
- When an Agent names a remote MCP server, the check pod also asks the server for its tools, through its Custodian. Each
|
|
322
|
+
name in an allowlist must be a tool of the server:
|
|
323
|
+
`error: mcp: workflow "<workflow>": Agent "<slot>" allowlists the tool "<tool>", which "<server>" does not list — it lists: <tools> (ADR-0079)`.
|
|
324
|
+
A server that refuses the token (a 401 or a 403) is an error too:
|
|
325
|
+
`error: mcp: "<server>" at <url> refused the request from a pod on <where> (HTTP <status>) — a wrong or expired value of <NAME>, or a binding of it (hosts, headers, paths) that does not let its Stand-in through to the url; every call of an Agent that names it would fail (ADR-0079)`.
|
|
326
|
+
A server that does not answer is a warning. [Give an Agent MCP tools](give-an-agent-mcp-tools.md#rules) gives each
|
|
327
|
+
text.
|
|
319
328
|
|
|
320
329
|
- Each rollout must complete. The error starts with
|
|
321
330
|
`error: <part>: rollout did not complete in namespace <namespace> — the pods say:`. See
|
|
@@ -330,9 +339,12 @@ refusals of a push and of the [Effector](../reference/glossary.md#effector) imag
|
|
|
330
339
|
``error: <layer>: rollout reported success, but the running pod carries <images> — expected <image>. The cluster is serving code this converge did not deploy; `kubectl -n <namespace> rollout restart deploy` and re-run `jr2 up` to resolve it.``
|
|
331
340
|
- When the rollout completes but no pod matches, `jr2 up` cannot check the image. It continues:
|
|
332
341
|
`<layer>: WARNING — rollout succeeded but no pod matched <selector> (nothing verified)`
|
|
333
|
-
- Before the publish, the Orchestrator must read the
|
|
334
|
-
`jr2 up`
|
|
335
|
-
|
|
342
|
+
- Before the publish, the Orchestrator must read the maps that `jr2 up` wrote, and the digests of the Caller tokens and
|
|
343
|
+
the Hook secrets. With no publish, `jr2 up` waits for the digests only. When the Orchestrator does not read them in
|
|
344
|
+
time, `jr2 up` stops with exit code 1:
|
|
345
|
+
``refusing: after <seconds>s the Orchestrator still reads an older <names> from its mount — the kubelet has not refreshed it; <what this means>. Run `jr2 up` again``
|
|
346
|
+
`<what this means>` is `nothing was published, and the previous Assembly is still current`, or
|
|
347
|
+
`a Caller token or Hook secret that this converge wrote does not work yet`, or both.
|
|
336
348
|
- The Orchestrator checks the Assembly again before it makes it current. It loads each Workflow and `jr2.config.ts`. It
|
|
337
349
|
refuses an [Open](../reference/glossary.md#open) part that nobody bound, a secret that the config does not declare, a
|
|
338
350
|
Kit version that is not its own, and a zod `input` that no door reads (a Machine that `jr2Setup` did not make). The
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Give a Caller a scope
|
|
3
|
+
description: Make a named token for a CI job or a bridge, give it only the scopes that it needs, and rotate it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Give a Caller a scope
|
|
7
|
+
|
|
8
|
+
Give a CI job, a bridge or a script a token of its own, with only the scopes that it needs.
|
|
9
|
+
|
|
10
|
+
A [Caller](../reference/glossary.md#caller) is a client that acts on the Instance from outside its
|
|
11
|
+
[Machines](../reference/glossary.md#machine). The CLI on your kubectl context is the Caller `token/instance`, and it can
|
|
12
|
+
do everything. A named Caller token can do less. Declare each one in
|
|
13
|
+
[`callers.tokens`](../reference/config.md#callers-tokens) of `jr2.config.ts`, with its scopes. This example declares
|
|
14
|
+
three. It needs the [Workflow](../reference/glossary.md#workflow) `release` with its
|
|
15
|
+
[Gate](../reference/glossary.md#gate) `review`: save `workflows/release.ts` from [Answer a Gate](answer-a-gate.md) in
|
|
16
|
+
your Instance first. `jr2 up` refuses a `{ workflow, gates }` item for a Workflow that the Instance does not have (see
|
|
17
|
+
[Rules](#rules)).
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { defineConfig } from "@jr2/orchestrator";
|
|
21
|
+
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
callers: {
|
|
24
|
+
tokens: {
|
|
25
|
+
// A CI job: it starts runs of release and follows them, and does nothing else.
|
|
26
|
+
ci: { may: { start: ["release"], read: ["release"] } },
|
|
27
|
+
// A bridge to a chat service: it reads each run and answers the Gates of any Workflow.
|
|
28
|
+
"chat-bridge": { may: { read: "all", answer: "all" } },
|
|
29
|
+
// A release manager: it answers only the Gate "review" of release, and reads the runs of release.
|
|
30
|
+
"release-manager": { may: { read: ["release"], answer: [{ workflow: "release", gates: ["review"] }] } },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Each scope is `"all"`, or a list of the names of the Workflows that it opens:
|
|
37
|
+
|
|
38
|
+
| Scope | What the Caller can do |
|
|
39
|
+
| -------- | ----------------------------------------------------------------------------------- |
|
|
40
|
+
| `start` | Start a run. |
|
|
41
|
+
| `read` | Read the full state of a run, follow it, list the runs, and read its conversations. |
|
|
42
|
+
| `answer` | Answer a Gate, and read the open Gates. |
|
|
43
|
+
| `cancel` | Cancel a run. |
|
|
44
|
+
| `steer` | Send a [Steering message](../reference/glossary.md#steering-message) to an Agent. |
|
|
45
|
+
|
|
46
|
+
The list of `answer` can also hold an item that names single Gates of a Workflow: `{ workflow, gates }`. A Caller with
|
|
47
|
+
`answer: ["triage", { workflow: "release", gates: ["review"] }]` answers each Gate of `triage`, and only the Gate
|
|
48
|
+
`review` of `release`. The name of a Gate is its invoke id: the `id` of its `invoke`, or else the path of its state,
|
|
49
|
+
such as `review` or `review.open`. `jr2 up` refuses a name that the Machines of the Workflow do not have, and a name
|
|
50
|
+
that two Machines of the Workflow have. It cannot check the Gates of a runtime [Chart](../reference/glossary.md#chart),
|
|
51
|
+
so for a [Chart wrapper](../reference/glossary.md#chart-wrapper) it warns and does not refuse.
|
|
52
|
+
[`jr2 gates`](../reference/cli.md#gates) and `GET /runs/:runId` show only the Gates that the Caller can answer. A value
|
|
53
|
+
of the `groups` map of an issuer takes the same item. Only `answer` takes it.
|
|
54
|
+
|
|
55
|
+
In the example, `release-manager` answers the Gate `review` of `release`, and no other Gate. When `release` has a second
|
|
56
|
+
Gate, such as a Gate for a security check, a different Caller answers it. `jr2 gates` with the token of
|
|
57
|
+
`release-manager` lists only the `review` Gates.
|
|
58
|
+
|
|
59
|
+
A scope that the entry does not give opens nothing. A scope does not limit what the run does: a run that a Caller starts
|
|
60
|
+
can start a run of a different Workflow with a [`dispatch`](../reference/authoring-surface/dispatch.md) Effect.
|
|
61
|
+
|
|
62
|
+
## Make the tokens
|
|
63
|
+
|
|
64
|
+
Run `jr2 up`. It makes the value of each new name one time, and keeps it in a Secret of its own:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
jr2 up
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
…
|
|
72
|
+
caller token "chat-bridge": made — `jr2 caller token chat-bridge` prints it, and it works when `jr2 up` says converged
|
|
73
|
+
caller token "ci": made — `jr2 caller token ci` prints it, and it works when `jr2 up` says converged
|
|
74
|
+
caller token "release-manager": made — `jr2 caller token release-manager` prints it, and it works when `jr2 up` says converged
|
|
75
|
+
…
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The [Orchestrator](../reference/glossary.md#orchestrator) gets only the SHA-256 digest of each value. A value is `jr2c_`
|
|
79
|
+
and 43 more characters.
|
|
80
|
+
|
|
81
|
+
## Give the token to the Caller
|
|
82
|
+
|
|
83
|
+
Print the value with [`jr2 caller token`](../reference/cli.md#caller-token). It reads the Secret over the Kubernetes
|
|
84
|
+
API, so your Kubernetes RBAC decides who can read it:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
jr2 caller token ci
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
→ context <context> / namespace <namespace>
|
|
92
|
+
jr2c_<value>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Only the value goes to stdout. Put it in the secret store of the CI job, as `JR2_TOKEN`. Keep it as you keep a password.
|
|
96
|
+
|
|
97
|
+
## Check what the token can do
|
|
98
|
+
|
|
99
|
+
The Caller reaches the Orchestrator at a URL. In a new terminal, forward a port to the Orchestrator. Keep this command
|
|
100
|
+
open:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
kubectl -n <namespace> port-forward svc/jr2-orchestrator 4000:4000
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Run [`jr2 whoami`](../reference/cli.md#whoami) with the token:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
JR2_URL=http://localhost:4000 JR2_TOKEN=$(jr2 caller token ci) jr2 whoami
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
→ http://localhost:4000
|
|
114
|
+
{"via":"token","name":"ci","may":{"start":["release"],"read":["release"]}}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The CI job runs `jr2 run`, `jr2 status` and `jr2 watch` with the same two variables, as
|
|
118
|
+
[Start a run](start-a-run.md#use-the-cli-without-the-instance-folder) shows. The run records its Caller in `startedBy`,
|
|
119
|
+
and `jr2 status` prints it on stderr as `started by: token/ci`.
|
|
120
|
+
|
|
121
|
+
## Rotate a token
|
|
122
|
+
|
|
123
|
+
Run [`jr2 caller rotate`](../reference/cli.md#caller-rotate). It makes a new value, and prints no value:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
jr2 caller rotate ci
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
→ context <context> / namespace <namespace>
|
|
131
|
+
caller token "ci": waiting for the kubelet to deliver jr2-caller-digests to the Orchestrator
|
|
132
|
+
caller token "ci": rotated — the old value no longer works; `jr2 caller token ci` prints the new one
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Give the new value to the Caller. No pod restarts.
|
|
136
|
+
|
|
137
|
+
## Remove a token
|
|
138
|
+
|
|
139
|
+
Remove its entry from `callers.tokens`, and run `jr2 up`. It deletes the Secret of the name, and the value stops
|
|
140
|
+
working:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
…
|
|
144
|
+
caller token "chat-bridge": deleted — callers.tokens no longer declares it
|
|
145
|
+
…
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Rules
|
|
149
|
+
|
|
150
|
+
- The config load refuses a name that is not a DNS label of 40 characters or fewer:
|
|
151
|
+
`<file> at callers.tokens.<name>: a token name is lowercase letters, digits and -, at most 40, starts with a letter and ends with a letter or digit — <shape>`.
|
|
152
|
+
`<shape>` is the shape of the `callers` block.
|
|
153
|
+
- The config load refuses the name `instance`, which is the name of the Instance token:
|
|
154
|
+
`<file> at callers.tokens.instance: the name instance is the Instance token's — <shape>`
|
|
155
|
+
- The config load refuses a scope that is not one of the five, and a list with no Workflow:
|
|
156
|
+
`<file> at callers.tokens.<name>.may<path>: <problem> — <shape>`
|
|
157
|
+
- The config load refuses an item `{ workflow, gates }` in a scope other than `answer`. `<problem>` is then:
|
|
158
|
+
`only "answer" can name single Gates; "<scope>" names whole Workflows, because it acts on a whole run`
|
|
159
|
+
- `jr2 up` and `jr2 check` check each `{ workflow, gates }` item of `callers.tokens` and of the `groups` map of each
|
|
160
|
+
issuer. Each line starts with the place of the item: `callers.tokens.<name>.may.answer` for a token, or
|
|
161
|
+
`callers.issuers.<index>.groups.<group>.answer` for an issuer. The lines below show the token form.
|
|
162
|
+
- They refuse a Gate name that the Machines of the Workflow do not have. The line lists the Gates that the Workflow has,
|
|
163
|
+
as `its Gates are "<gate>", "<gate>"`, or `it has no Gate` when it has none:
|
|
164
|
+
`callers.tokens.<name>.may.answer: Workflow "<workflow>" has no Gate "<gate>" — a Gate's name is its invoke id: the invoke id that the author wrote, or else the key path of its gated state; its Gates are "<gate>", "<gate>" (ADR-0011, ADR-0078)`
|
|
165
|
+
- They refuse a Gate name that two Machines of the Workflow have:
|
|
166
|
+
`callers.tokens.<name>.may.answer: Gate "<gate>" of Workflow "<workflow>" is in more than one Machine (<machines>), so the one name would open each of those Gates: give one of them an invoke id of its own (ADR-0078)`
|
|
167
|
+
- They refuse an item for a Workflow that the [Assembly](../reference/glossary.md#assembly) does not register:
|
|
168
|
+
`callers.tokens.<name>.may.answer: { workflow: "<workflow>", gates } names the Gates of a Workflow that this Assembly does not register, so jr2 cannot check them: name a registered Workflow or a Chart file (ADR-0078)`
|
|
169
|
+
- For a Chart wrapper that takes runtime Charts, a Gate name that jr2 cannot find is a warning, not a refusal. The line
|
|
170
|
+
ends with `; a runtime Chart of it may have one, which jr2 up cannot check`.
|
|
171
|
+
- An item for `<wrapper>/<name>` that is no Chart file of the Assembly is a warning when the wrapper takes runtime
|
|
172
|
+
Charts:
|
|
173
|
+
`callers.tokens.<name>.may.answer: { workflow: "<wrapper>/<name>", gates } names a Chart that is no Chart file of this Assembly; a runtime Chart's Gates cannot be checked at jr2 up (ADR-0070, ADR-0078)`
|
|
174
|
+
- When the wrapper takes no runtime Chart, the same item is a refusal, and the line ends with
|
|
175
|
+
`, and "<wrapper>" takes no runtime Chart`.
|
|
176
|
+
- The Orchestrator refuses a value that it does not know, such as a value from before a rotation, with the status code
|
|
177
|
+
`401`: `unauthorized`. `jr2 caller rotate` returns when the Orchestrator has read the new digest, so the old value no
|
|
178
|
+
longer works then.
|
|
179
|
+
- The Orchestrator refuses a request that needs a scope that the token does not have for the Workflow, with the status
|
|
180
|
+
code `403`: `the Caller token/<name> needs the "<scope>" scope for Workflow "<workflow>" (ADR-0078)`
|
|
181
|
+
- It refuses an answer to a Gate that an `answer` item with `gates` does not name, with the status code `403`:
|
|
182
|
+
`the Caller token/<name> needs the "answer" scope for Gate "<gate>" of Workflow "<workflow>" (ADR-0078)`. The body
|
|
183
|
+
also holds `scope`, `workflow` and `gate`.
|
|
184
|
+
- It refuses a request that needs a scope that the token has for no Workflow, with the status code `403`:
|
|
185
|
+
`the Caller token/<name> has no "<scope>" scope for any Workflow (ADR-0078)`
|
|
186
|
+
- It refuses a route that no scope opens, such as a runtime Chart, with the status code `403`:
|
|
187
|
+
`this route needs the Instance token: no scope opens it, so the Caller token/<name> cannot`
|
|
188
|
+
- `jr2 caller token` prints nothing on stdout and exits with `1` when the Secret is not there:
|
|
189
|
+
``error: no Caller token "<name>" here (context <context>, namespace <namespace>) — declare it in callers.tokens of jr2.config.ts, then `jr2 up` makes it``
|
|
190
|
+
- `jr2 caller rotate` changes nothing and exits with `1` when the Secret is not there:
|
|
191
|
+
``error: no Caller token "<name>" in namespace "<namespace>" — declare it in callers.tokens of jr2.config.ts and run `jr2 up` (tokens here: <names>)``.
|
|
192
|
+
The part `(tokens here: <names>)` shows only when the namespace has a token.
|
|
193
|
+
- `jr2 caller token` and `jr2 caller rotate` take `-n` and `--context`, and not `--url`: the Orchestrator holds no
|
|
194
|
+
value.
|
|
195
|
+
|
|
196
|
+
## Read next
|
|
197
|
+
|
|
198
|
+
- [Callers and Hooks](../concepts/callers-and-hooks.md)
|
|
199
|
+
- [Secrets and trust](../concepts/secrets-and-trust.md)
|
|
200
|
+
- [ADR-0078](../reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md): the
|
|
201
|
+
Callers, the scopes, and the named tokens.
|
|
202
|
+
- [ADR-0014](../reference/decisions/0014-observation-is-open-run-state-is-not.md): which scope opens which route.
|
|
203
|
+
- [Start a run](start-a-run.md)
|