@sigrun/sigrun 0.2.0 → 0.3.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/CHANGELOG.md +145 -7
- package/README.md +333 -13
- package/dist/blocks/build-stamp.json +13 -0
- package/dist/blocks/builders.d.ts +57 -0
- package/dist/blocks/images.d.ts +26 -0
- package/dist/blocks/index.d.ts +20 -0
- package/dist/blocks/limits.d.ts +25 -0
- package/dist/blocks/placements.d.ts +26 -0
- package/dist/blocks/schema.d.ts +38 -0
- package/dist/blocks/validate.d.ts +73 -0
- package/dist/cli.js +117 -19
- package/dist/config.js +21 -2
- package/dist/extension.d.ts +48 -8
- package/dist/harness/ambient.js +2 -0
- package/dist/harness/blocks/state.js +1 -0
- package/dist/harness/boot.js +92 -6
- package/dist/harness/builtins.js +1 -1
- package/dist/harness/context.js +25 -0
- package/dist/harness/event-bus.js +25 -14
- package/dist/harness/identity/accounts.js +3 -2
- package/dist/harness/identity/index.js +2 -1
- package/dist/harness/identity/invites.js +26 -9
- package/dist/harness/identity/link-sweep.js +47 -0
- package/dist/harness/identity/typed-username.js +15 -0
- package/dist/harness/identity/users.js +10 -7
- package/dist/harness/interactions.js +2 -0
- package/dist/harness/loader.js +57 -1
- package/dist/harness/migration-snapshot.js +97 -0
- package/dist/harness/reports.js +100 -0
- package/dist/harness/seam-host.js +23 -1
- package/dist/harness/sections/context-files.js +1 -1
- package/dist/harness/settings.js +52 -4
- package/dist/jobs/docs.js +3 -0
- package/dist/jobs/fire.js +2 -0
- package/dist/jobs/parked.js +38 -0
- package/dist/jobs/task.js +37 -8
- package/dist/sandbox/availability.js +69 -20
- package/dist/sandbox/launch.js +11 -0
- package/dist/sandbox/policy.js +24 -3
- package/dist/sandbox/worker.js +4 -24
- package/dist/serve.js +162 -40
- package/dist/server/auth/ip.js +9 -4
- package/dist/server/auth/own-host.js +115 -0
- package/dist/server/auth/pipeline.js +93 -28
- package/dist/server/auth/proxy-diagnostic.js +60 -0
- package/dist/server/auth/proxy-identity.js +134 -0
- package/dist/server/auth/proxy-only.js +28 -0
- package/dist/server/images/cache.js +13 -5
- package/dist/server/index.js +10 -2
- package/dist/server/login/resolve.js +88 -26
- package/dist/server/notifications.js +21 -4
- package/dist/server/routes/admin.js +97 -0
- package/dist/server/routes/images.js +16 -9
- package/dist/server/routes/login.js +8 -0
- package/dist/server/routes/me.js +1 -1
- package/dist/server/routes/meta.js +4 -0
- package/dist/server/routes/metrics.js +18 -2
- package/dist/server/routes/onboarding.js +97 -37
- package/dist/server/session-meta.js +1 -0
- package/dist/server/shutdown.js +93 -16
- package/dist/settings/registry.js +6 -0
- package/node_modules/@sigrun/shared/CHANGELOG.md +12 -0
- package/node_modules/@sigrun/shared/dist/settings.d.ts +14 -0
- package/node_modules/@sigrun/shared/dist/usernames.d.ts +8 -0
- package/node_modules/@sigrun/shared/dist/usernames.js +39 -0
- package/node_modules/@sigrun/shared/dist/views.d.ts +33 -4
- package/node_modules/@sigrun/shared/package.json +5 -1
- package/package.json +16 -15
- package/webui/dist/assets/{index-CxB969qp.js → index-CEOzj1C4.js} +11 -11
- package/webui/dist/index.html +1 -1
- package/CONTEXT.md +0 -163
- package/dist/server/login/usernames.js +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,125 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-10-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Parked-task visibility and recovery: pi-durable reports now reach logs,
|
|
14
|
+
metrics, alerts, and job status, and administrators can list and retry
|
|
15
|
+
parked tasks through the admin API.
|
|
16
|
+
- Proxy identity links with case-insensitive matching, plus typed-username
|
|
17
|
+
normalization for `user add --proxy`, `link`, and `unlink`.
|
|
18
|
+
- An optional chart `networkPolicy`, `OnboardingState.proxyIdentity.subject`,
|
|
19
|
+
the ProxyUnidentified screen, and the shared `./usernames` export.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Upgraded the Earendil runtime to pi-durable 1.4.0 (with chord and pi-ai
|
|
23
|
+
1.4.0), including durable schedule sleeps, retry backoffs that survive
|
|
24
|
+
restarts, and the crash-loop parked-task guard.
|
|
25
|
+
- Extension shutdown now runs in parallel within a fixed budget, with the
|
|
26
|
+
chart's termination grace period matched to that budget.
|
|
27
|
+
- The loader quarantines extensions whose declared Earendil peer range
|
|
28
|
+
excludes the host version instead of allowing an incompatible extension
|
|
29
|
+
to fail later at runtime.
|
|
30
|
+
- `settings.compaction.modelOverrides` supports per-model compaction
|
|
31
|
+
settings while preserving environment-over-file precedence.
|
|
32
|
+
- Proxy-only non-loopback boots refuse unvouched account creation, including
|
|
33
|
+
login and code paths, and mint no setup code there. Login derives from the
|
|
34
|
+
full email; boot sweeps orphaned proxy links, gates own-host peers, and
|
|
35
|
+
throttles proxy diagnostics.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- CLI empty-string identity values now mean "unset".
|
|
39
|
+
|
|
40
|
+
### Breaking
|
|
41
|
+
- When `SIGRUN_API_TOKEN` is set, `SIGRUN_API_TOKEN_USER` must be a valid
|
|
42
|
+
username key (the validation error includes a derivation suggestion). The
|
|
43
|
+
user value is validated only when the token is set.
|
|
44
|
+
|
|
45
|
+
### Upgrade notes
|
|
46
|
+
- **One-way storage migration:** the first 0.3.0 boot migrates the SQLite
|
|
47
|
+
durable schema to pi-durable 1.4.0's format. Before opening storage, boot
|
|
48
|
+
writes a crash-consistent snapshot beside the database named
|
|
49
|
+
`<storagePath>.pre-durable-schema-v<CURRENT>-<UTC stamp>.bak`. Snapshots
|
|
50
|
+
are never deleted automatically. If a needed snapshot cannot be written,
|
|
51
|
+
boot stops before migration. `SIGRUN_SKIP_MIGRATION_SNAPSHOT=1` is the
|
|
52
|
+
emergency opt-out for an operator with an independent backup.
|
|
53
|
+
- **Rollback to 0.2.x (SQLite):** stop sigrun, restore the `.bak` over the
|
|
54
|
+
database file, remove the database's `-wal` and `-shm` sidecars, then
|
|
55
|
+
deploy 0.2.x. Anything committed after the upgrade is lost.
|
|
56
|
+
- **JSONL storage:** there is no snapshot because its schema does not
|
|
57
|
+
change. A 0.2.x process nevertheless never resumes a task left `sleeping`
|
|
58
|
+
by 0.3.0, so rollback can strand that task.
|
|
59
|
+
|
|
60
|
+
## [0.2.1] - 2026-10-28
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
- `GET /v1/meta` now reports the effective listener: `listener.host`,
|
|
64
|
+
`listener.port`, and `listener.families` — the address families the
|
|
65
|
+
live listener accepts, measured once at listen (the `::` wildcard
|
|
66
|
+
probes both loopbacks and reports exactly the families that connect;
|
|
67
|
+
a hostname bind reports the bound socket's family, never a concrete
|
|
68
|
+
peer address). Additive wire field: pre-upgrade servers omit
|
|
69
|
+
`listener`; clients consuming it must tolerate its absence.
|
|
70
|
+
- `SIGRUN_LISTEN_HOST` is now honored as the environment equivalent of
|
|
71
|
+
the programmatic `serve({host})` option. One host value is resolved
|
|
72
|
+
at the serving boundary (`options.host` → `SIGRUN_LISTEN_HOST` → `::`)
|
|
73
|
+
and drives the bind AND both auth derivations — the previously split
|
|
74
|
+
defaults (the boot auth derivation's independent env read, and the
|
|
75
|
+
harness-side `0.0.0.0` fallback) are gone.
|
|
76
|
+
- Proxy-auth rejections (401) now log one sanitized `warn` per rejected
|
|
77
|
+
request: the socket peer, the method, a short reason (`untrusted
|
|
78
|
+
proxy`, `missing or wrong shared secret`, `missing identity header`,
|
|
79
|
+
`untrusted identity source`), and the resolved route template — never
|
|
80
|
+
tokens, cookies, identity-header values, query strings, or the full
|
|
81
|
+
URL. Token-auth failures and successful proxy authentications stay
|
|
82
|
+
silent.
|
|
83
|
+
- The normal core build now emits real `dist/blocks/**/*.d.ts`
|
|
84
|
+
declarations, including the `dist/blocks/index.d.ts` named by the
|
|
85
|
+
`@sigrun/sigrun/blocks` export. Pack/type-resolution coverage compiles
|
|
86
|
+
an external consumer against those declarations; extension consumers
|
|
87
|
+
no longer need an ambient block-module shim.
|
|
88
|
+
|
|
89
|
+
### Fixed
|
|
90
|
+
- Successful `PUT /v1/me/extensions/:slug/settings` writes now publish
|
|
91
|
+
through the same post-commit settings-change seam as section saves:
|
|
92
|
+
one per-user failure-fence clear, one observing-extension reconciliation,
|
|
93
|
+
and the extension slug plus changed body keys. Invalid, unknown, and
|
|
94
|
+
otherwise rejected writes publish nothing; repeated successful writes
|
|
95
|
+
retain the existing notification semantics.
|
|
96
|
+
- `host.peekInteraction(conversationId, callId, context)`: a
|
|
97
|
+
non-consuming interaction inspection read beside
|
|
98
|
+
`snapshotInteraction`. It returns the same stored record projection
|
|
99
|
+
(secret values stay masked) but NEVER touches the one-shot raw-secret
|
|
100
|
+
delivery — safe to repeat for notifiers, outcome edits, and answer
|
|
101
|
+
correlation. `snapshotInteraction` remains the ONLY read that merges
|
|
102
|
+
and consumes an unread delivery, reserved for the interaction's
|
|
103
|
+
owning extension; its first-read/second-read semantics are unchanged.
|
|
104
|
+
- `NotificationEvent` is now a discriminated union (shared base plus
|
|
105
|
+
`interaction.pending` / `job.failed` / `run.settled` variants), and
|
|
106
|
+
the `run.settled` variant carries a structured
|
|
107
|
+
`outcome: { status: "answered" } | { status: "unanswered"; reason: string }`
|
|
108
|
+
translated directly from the host event's existing `outcome`/`reason`
|
|
109
|
+
(no second answer read, no inferred status). The other variants do
|
|
110
|
+
not gain the field; exhaustive narrowing on `type` now typechecks.
|
|
111
|
+
|
|
112
|
+
### Fixed (continued)
|
|
113
|
+
- Restored per-user worker startup by placing the selected device paths
|
|
114
|
+
under read-only Landlock rules. Their ordinary I/O works, while
|
|
115
|
+
`/dev/shm` and writes outside workspace/home/tmp remain denied.
|
|
116
|
+
- Preserved composer text and attachments when a slow conversation-meta
|
|
117
|
+
restore resolves after a local edit or clear. The interaction visual
|
|
118
|
+
drain now covers required secrets and multi-step forms, and the visual
|
|
119
|
+
e2e gate passes all 163 cases.
|
|
120
|
+
|
|
121
|
+
### Changed
|
|
122
|
+
- Settled-run notifications are truthful: an answered run keeps the
|
|
123
|
+
`"Reply ready"` title, while an unanswered run (model error, abort,
|
|
124
|
+
or a missing answer) is titled `"Run ended without a reply"` with the
|
|
125
|
+
settle reason appended to the body — a failed run no longer
|
|
126
|
+
masquerades as a ready reply. Recipient, dedup, and
|
|
127
|
+
`notifications.runSettled` gating are unchanged.
|
|
128
|
+
|
|
10
129
|
## [0.2.0] - 2026-10-27
|
|
11
130
|
### Added
|
|
12
131
|
- Per-user extension surface (multi-user M2): lifecycle events carry the
|
|
@@ -58,11 +177,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
58
177
|
literal-content ruling.
|
|
59
178
|
- Images (U7): an HMAC-signed proxy, a rebinding-safe fetcher, an LRU cache
|
|
60
179
|
with `sharp` conversion, and CSP headers.
|
|
61
|
-
- Core settings sections rebuilt on blocks (U4): one settings renderer for
|
|
62
|
-
webui and TUI, extension-declared sections, a `/v1/settings` sections
|
|
63
|
-
route, `pendingRestart` with an admin restart route, live/restart
|
|
64
|
-
metadata for every core key, label search, and
|
|
65
|
-
`settings.changed`/`onSettingsChanged`.
|
|
66
180
|
|
|
67
181
|
### Changed
|
|
68
182
|
- Family versions move together to 0.2.0: `@sigrun/shared` 0.2.0
|
|
@@ -91,6 +205,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
91
205
|
distinguish Landlock denials from Yama or missing-capability conditions.
|
|
92
206
|
|
|
93
207
|
## [0.1.7] - 2026-10-24
|
|
208
|
+
|
|
209
|
+
*Correction (2026-10-28): the original entry omitted substantial scope
|
|
210
|
+
that shipped in this release — the U4 settings rebuild, the M3a
|
|
211
|
+
account-link store and routes, and the accompanying `@sigrun/shared` /
|
|
212
|
+
`@sigrun/tui` settings-surface work. Those entries are restored below;
|
|
213
|
+
the Service-migration claim is also corrected (adding a secondary
|
|
214
|
+
family while retaining the primary is an in-place patch, not a
|
|
215
|
+
recreate).*
|
|
216
|
+
|
|
217
|
+
### Added
|
|
218
|
+
- Core settings sections rebuilt on blocks (U4): one settings renderer
|
|
219
|
+
for webui and TUI, extension-declared sections, a `/v1/settings`
|
|
220
|
+
sections route, `pendingRestart` with an admin restart route,
|
|
221
|
+
live/restart metadata for every core key, label search, and
|
|
222
|
+
`settings.changed`/`onSettingsChanged`. The shared and TUI packages
|
|
223
|
+
carry the matching settings-surface and settings-form work (live
|
|
224
|
+
surface revs, default-on toggle handling, roster-driven tool
|
|
225
|
+
defaults, walk-based search).
|
|
226
|
+
- Account links (multi-user M3a): the core account-link store plus
|
|
227
|
+
routes to list and remove an account's linked external identities.
|
|
228
|
+
|
|
94
229
|
### Fixed
|
|
95
230
|
- The deploy entry binds the dual-stack wildcard (`::`) instead of the
|
|
96
231
|
IPv4-only `0.0.0.0`. On a dual-stack pod whose Service is IPv6-only
|
|
@@ -107,8 +242,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
107
242
|
### Changed
|
|
108
243
|
- The chart's main Service is `PreferDualStack` over `[IPv6, IPv4]`,
|
|
109
244
|
so it advertises both pod addresses regardless of the cluster's
|
|
110
|
-
default family.
|
|
111
|
-
|
|
245
|
+
default family. Adding a secondary family while retaining the
|
|
246
|
+
primary is an in-place patch (`spec.ipFamilies` gains the new
|
|
247
|
+
family); only changing the PRIMARY family requires recreation
|
|
248
|
+
(`spec.clusterIPs` is immutable). *Corrected 2026-10-28: the
|
|
249
|
+
original entry claimed every conversion is a recreate.*
|
|
112
250
|
- `sigrun run` (workstation mode) still binds `127.0.0.1` only.
|
|
113
251
|
|
|
114
252
|
## [0.1.6] - 2026-10-24
|
package/README.md
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
# Sigrun
|
|
2
2
|
|
|
3
|
-
Sigrun is a durable personal-assistant
|
|
4
|
-
[pi-durable](https://www.npmjs.com/package/@earendil-works/pi-durable)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Sigrun is a **durable, multi-user personal-assistant server** built on
|
|
4
|
+
[pi-durable](https://www.npmjs.com/package/@earendil-works/pi-durable).
|
|
5
|
+
One agent loop serves every surface — a web UI, a terminal UI, an HTTP
|
|
6
|
+
API, and (via the gateway extension) chat channels — over long-lived
|
|
7
|
+
conversations stored in SQLite.
|
|
8
|
+
An extension model installs extra tools, providers, prompt sections,
|
|
9
|
+
memory systems, and login providers at boot.
|
|
10
|
+
|
|
11
|
+
**Why use it?** Conversations survive restarts and resume where they
|
|
12
|
+
stopped; memory and integrations are extension-owned and individually
|
|
13
|
+
replaceable; multi-user boundaries are explicit (real authentication plus
|
|
14
|
+
a per-user execution jail); and it deploys as an npm package, a Docker
|
|
15
|
+
compose reference, or a Helm chart. [`docs/why.md`](docs/why.md) is the
|
|
16
|
+
longer rationale.
|
|
17
|
+
|
|
18
|
+
**Status:** 0.x — useful and exercised, but extension and settings
|
|
19
|
+
contracts can still evolve between minor releases. See
|
|
20
|
+
[`SECURITY.md`](SECURITY.md) for the support, trust, and verification
|
|
21
|
+
posture, and [`CONTRIBUTING.md`](CONTRIBUTING.md) to build and test.
|
|
22
|
+
|
|
23
|
+
**Try it:** `npm i -g @sigrun/sigrun && sigrun run` — or jump to
|
|
24
|
+
[Install](#install) and [Quickstart](#quickstart) for the model/credential
|
|
25
|
+
setup every install needs.
|
|
9
26
|
|
|
10
27
|
- **Durable** — conversations, submissions, and schedules live in one
|
|
11
28
|
SQLite database (`SIGRUN_STORAGE_PATH`); a restart resumes where it
|
|
@@ -156,7 +173,9 @@ still override it per field.
|
|
|
156
173
|
| `OPENAI_API_KEY` | string | — | `auth.json` (see below) | Credential for the env-driven OpenAI-compatible provider; the `auth.json` fallback after file entries. |
|
|
157
174
|
| `OPENAI_BASE_URL` | URL | OpenAI | `defaultProvider.baseUrl` | Endpoint for the env-driven provider (any compatible host). |
|
|
158
175
|
| `SIGRUN_PORT` | positive int | `3000` | `server.port` | HTTP listen port. |
|
|
176
|
+
| `SIGRUN_LISTEN_HOST` | host | `::` | — | HTTP listen host — the environment equivalent of the programmatic `serve({host})` option (the option wins when both are set). One resolved value drives the bind AND the auth defaults: a loopback bind derives the no-auth workstation posture, any other bind derives `token` auth. `GET /v1/meta` reports the effective listener (`listener.host`/`port`/`families`). |
|
|
159
177
|
| `SIGRUN_STORAGE_PATH` | path | `<dataDir>/sigrun.db` | `server.storagePath` | SQLite database location. Relative values resolve against the data root (absolute values verbatim; the cwd-relative `data/sigrun.db` default is retired). |
|
|
178
|
+
| `SIGRUN_SKIP_MIGRATION_SNAPSHOT` | `1` | *(unset)* | — | Skip the automatic pre-migration SQLite snapshot when set to `1`. Emergency escape hatch for an operator who already has an independent backup; without it, a needed snapshot failure stops boot before the one-way durable schema migration. |
|
|
160
179
|
| `SIGRUN_WORKSPACE_PATH` | path | `<dataDir>/workspace` | `server.workspacePath` | Root of the static local workspace every conversation's tools run against. The default rides the data root (chart/compose deploys set the path explicitly); it is never persisted on first boot. |
|
|
161
180
|
| `SIGRUN_DATA_DIR` | path | `$XDG_DATA_HOME/sigrun` or `~/.local/share/sigrun` | `server.dataDir` | Data root (the DB default and extension data dirs). Env/file values win verbatim. |
|
|
162
181
|
| `SIGRUN_CACHE_DIR` | path | `$XDG_CACHE_HOME/sigrun` or `~/.cache/sigrun` | `server.cacheDir` | Cache root (regenerable; never ensured at boot). Env/file values win verbatim. |
|
|
@@ -165,6 +184,7 @@ still override it per field.
|
|
|
165
184
|
| — | — | *(none)* | `gitDir` is always `<configDir>/git` | Git extension checkouts clone here (pi layout). Not env-configurable. |
|
|
166
185
|
| `SIGRUN_WEBUI_BUNDLE` | path | `webui/dist` | `server.webuiBundle` | Web UI bundle directory; explicit-but-missing = boot error, default-missing = API-only. |
|
|
167
186
|
| `SIGRUN_CONFIG_DIR` | path | `~/.config/sigrun` | *env-only* | The settings file's own directory. |
|
|
187
|
+
| `SIGRUN_API_TOKEN_USER` | username key | `sigrun` | *env-only* | User for `SIGRUN_API_TOKEN`. Must already be a valid username key (`^[a-z0-9][a-z0-9._-]*$`, at most 128 characters); invalid values fail boot with a derivation suggestion. Validated only when `SIGRUN_API_TOKEN` is non-empty. |
|
|
168
188
|
| `SIGRUN_COMPACTION_ENABLED` | `true`/`false` | `true` | `server.compaction.enabled` | Context compaction on/off. |
|
|
169
189
|
| `SIGRUN_COMPACTION_RESERVE_TOKENS` | positive int | `16384` | `server.compaction.reserveTokens` | Headroom reserved for the model's reply. |
|
|
170
190
|
| `SIGRUN_COMPACTION_KEEP_RECENT_TOKENS` | positive int | `20000` | `server.compaction.keepRecentTokens` | Recent context retained verbatim through a compaction. |
|
|
@@ -174,6 +194,32 @@ still override it per field.
|
|
|
174
194
|
| `SIGRUN_BACKUP_S3_PREFIX` | string | *(unset)* | `server.backup.s3.prefix` | Key prefix within the bucket. |
|
|
175
195
|
| `SIGRUN_BACKUP_S3_ENDPOINT` | URL | AWS default | `server.backup.s3.endpoint` | Custom S3 endpoint (S3-compatible stores). |
|
|
176
196
|
|
|
197
|
+
Per-model overrides: `server.compaction.modelOverrides` is a map keyed by
|
|
198
|
+
the exact `provider/modelId` string pi-durable composes — note that a
|
|
199
|
+
chain-shaped model id doubles the prefix. Use it when a small-window model
|
|
200
|
+
must sit alongside the large-window default policy (lower
|
|
201
|
+
`reserveTokens`/`keepRecentTokens`/`backgroundTokens`, or `enabled: false`
|
|
202
|
+
for a model that must never compact):
|
|
203
|
+
|
|
204
|
+
```jsonc
|
|
205
|
+
"server": {
|
|
206
|
+
"compaction": {
|
|
207
|
+
"reserveTokens": 16384,
|
|
208
|
+
"modelOverrides": {
|
|
209
|
+
// Synthetic example: provider "bifrost", model id "bifrost/small-chat".
|
|
210
|
+
"bifrost/bifrost/small-chat": { "reserveTokens": 4096, "keepRecentTokens": 6000 }
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Each entry is a partial policy (the same fields and minimums as the parent
|
|
217
|
+
block); unset fields inherit the global policy. Boot-time lifetime like the
|
|
218
|
+
rest of compaction, and there is no env spelling. After the boot catalog
|
|
219
|
+
refresh an override key that matches no known model logs one warning
|
|
220
|
+
(`compaction override "<key>" matches no known model`) — never an error,
|
|
221
|
+
since catalogs move.
|
|
222
|
+
|
|
177
223
|
### settings.json schema
|
|
178
224
|
|
|
179
225
|
```jsonc
|
|
@@ -200,7 +246,10 @@ still override it per field.
|
|
|
200
246
|
"enabled": true,
|
|
201
247
|
"reserveTokens": 16384, // positive integer
|
|
202
248
|
"keepRecentTokens": 20000, // positive integer
|
|
203
|
-
"backgroundTokens": 32768
|
|
249
|
+
"backgroundTokens": 32768, // non-negative integer (0 = off)
|
|
250
|
+
"modelOverrides": { // per-model partial policies, keyed by exact provider/modelId
|
|
251
|
+
"bifrost/bifrost/small-chat": { "reserveTokens": 4096 }
|
|
252
|
+
}
|
|
204
253
|
},
|
|
205
254
|
"backup": { // target: { "path": "/backups" } XOR { "s3": { "bucket": "...", "prefix": "...", "endpoint": "..." } }
|
|
206
255
|
"staleAfterHours": 36 // positive number: health.backup degrades past this marker age
|
|
@@ -289,6 +338,64 @@ configurable) when the request comes from a peer inside
|
|
|
289
338
|
proxy and nothing else: every peer in `trustedProxies` can forge any
|
|
290
339
|
identity, including an admin.
|
|
291
340
|
|
|
341
|
+
**Which address to list.** `trustedProxies` must list the address the
|
|
342
|
+
proxy **connects from**, as the pod sees it — not the proxy's own
|
|
343
|
+
Service or DNS name. The same list also gates trust in
|
|
344
|
+
`X-Forwarded-Host` (the Origin check) and `X-Forwarded-Proto` (the
|
|
345
|
+
Secure-cookie decision): a peer outside the list cannot steer either.
|
|
346
|
+
On a dual-stack cluster the Service may be reached over either family
|
|
347
|
+
(the Service can be IPv6-first while the proxy still connects over
|
|
348
|
+
IPv4), so list every address the proxy actually sources from.
|
|
349
|
+
|
|
350
|
+
**Cilium Gateway API / Ingress.** The connect-from address is the
|
|
351
|
+
per-node **Cilium ingress IP**, allocated from that node's pod CIDR —
|
|
352
|
+
enumerate them with:
|
|
353
|
+
|
|
354
|
+
```sh
|
|
355
|
+
kubectl get ciliumnodes -o jsonpath='{..spec.ingress}'
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Listing those addresses exactly is the tightest posture. Trusting the
|
|
359
|
+
whole pod CIDR (e.g. `10.42.0.0/16`, `fd00:42::/64`) is acceptable
|
|
360
|
+
**only together with a policy admitting the `ingress` entity** — the
|
|
361
|
+
chart's `networkPolicy.enabled` option installs that
|
|
362
|
+
CiliumNetworkPolicy, whose default also admits `host` for kubelet
|
|
363
|
+
probes. Without it, any pod in the CIDR can forge
|
|
364
|
+
identity headers directly to the Service. Note that the `ingress`
|
|
365
|
+
entity covers **every Cilium gateway in the cluster**, so every route
|
|
366
|
+
to sigrun must pass through forward auth; a gateway route that skips
|
|
367
|
+
it is an open impersonation path.
|
|
368
|
+
|
|
369
|
+
**Forward-auth header hygiene.** Forward auth must return **every
|
|
370
|
+
identity header sigrun reads** on every authenticated response, and
|
|
371
|
+
its upstream-header mode must **override, not append** — Envoy's
|
|
372
|
+
`allowed_upstream_headers`, not `allowed_upstream_headers_to_append`.
|
|
373
|
+
With append semantics a client can supply the headers forward auth
|
|
374
|
+
omits and sigrun will read the client's copies.
|
|
375
|
+
|
|
376
|
+
**Own-host peers (C5).** A trusted **range** never vouches for
|
|
377
|
+
sigrun's own addresses — loopback or any local interface address —
|
|
378
|
+
without the shared secret, because every local process shares those
|
|
379
|
+
source addresses. An **exactly listed** local address (a bare address,
|
|
380
|
+
or a `/32` / `/128` entry) does vouch, as an explicit operator
|
|
381
|
+
decision, and boot logs a warning for each such entry when no shared
|
|
382
|
+
secret is configured.
|
|
383
|
+
|
|
384
|
+
**Rejection diagnostics.** Each rejection logs one sanitized line
|
|
385
|
+
(subject to the throttle below) naming the socket peer, the method, a
|
|
386
|
+
short reason, and the route, when known — never tokens, cookies, or
|
|
387
|
+
identity-header values. The throttle emits one line per reason per 60 s,
|
|
388
|
+
with `(N suppressed)` on the next line for that reason. The reasons:
|
|
389
|
+
|
|
390
|
+
| Reason | Meaning |
|
|
391
|
+
|---|---|
|
|
392
|
+
| `untrusted proxy` | The socket peer is outside `trustedProxies`. |
|
|
393
|
+
| `own-host peer without shared secret` | The peer is a local address trusted only through a range, and no shared secret is configured — see C5 above. |
|
|
394
|
+
| `missing or wrong shared secret (<header> header)` | The named secret header was absent or did not match `SIGRUN_PROXY_SECRET`. |
|
|
395
|
+
| `missing identity header (<header>)` | The proxy vouched but sent no user header — forward auth is not returning every identity header. |
|
|
396
|
+
| `unusable identity claim` | The vouched username cannot be a directory user (403 `invalid_username`). |
|
|
397
|
+
| `untrusted identity source` | The user does not exist and `autoProvision` is off (403 `user_not_provisioned`). |
|
|
398
|
+
|
|
292
399
|
**Stored groups and group-derived admin.** `server.auth.adminGroups`
|
|
293
400
|
lists groups (Authelia's `Remote-Groups`, for example) whose members act as
|
|
294
401
|
admins. Core stores groups per authenticating source: `proxy` for validated
|
|
@@ -311,6 +418,106 @@ until then. Token and session requests only read the stored record; they
|
|
|
311
418
|
never accept groups from the request. People-scoped conversation shares may
|
|
312
419
|
also name groups, matched against the same stored groups.
|
|
313
420
|
|
|
421
|
+
### Usernames
|
|
422
|
+
|
|
423
|
+
Every external identity — proxy header, OIDC subject, invite claim,
|
|
424
|
+
CLI argument — resolves to one **directory user key**. The key is the
|
|
425
|
+
stable identifier: it names the user's storage directory
|
|
426
|
+
(`<dataDir>/users/<user>`), their config directories, their per-user
|
|
427
|
+
extension stores, and it appears in tool registrations as
|
|
428
|
+
`<slug>@<user>`, split at the **first `@`**. The key pattern is
|
|
429
|
+
therefore a safety rule, not a style choice:
|
|
430
|
+
|
|
431
|
+
- lowercase letters, digits, `.`, `_`, `-` only, and no `/` against
|
|
432
|
+
traversal (case-insensitive filesystems would otherwise let `Alice`
|
|
433
|
+
and `alice` collide on one directory);
|
|
434
|
+
- must start with a letter or digit (no leading `.` against hidden
|
|
435
|
+
paths or `..` keys);
|
|
436
|
+
- no `@` — it is the tool-registration delimiter;
|
|
437
|
+
- at most 128 characters, bounding key length for storage and tool
|
|
438
|
+
names.
|
|
439
|
+
|
|
440
|
+
`deriveUsername(input)` maps any input onto that pattern: Unicode NFKD
|
|
441
|
+
and strip combining marks, lowercase, `@` → `_`, every other disallowed
|
|
442
|
+
character → `-` (no collapsing), strip leading non-alphanumerics,
|
|
443
|
+
truncate to 128. Empty result → no usable key: proxy authentication
|
|
444
|
+
refuses with 403 `invalid_username`, typed forms with 400, and login
|
|
445
|
+
derivation falls back to the literal key `user`. The normative vectors:
|
|
446
|
+
|
|
447
|
+
| Input | Key |
|
|
448
|
+
|---|---|
|
|
449
|
+
| `mikemacleod` | `mikemacleod` |
|
|
450
|
+
| `Mike` | `mike` |
|
|
451
|
+
| `mike@example.ca` | `mike_example.ca` |
|
|
452
|
+
| `mike@example.com` | `mike_example.com` |
|
|
453
|
+
| `Mike.Smith@Example.COM` | `mike.smith_example.com` |
|
|
454
|
+
| `mike+test@example.com` | `mike-test_example.com` |
|
|
455
|
+
| `José García` | `jose-garcia` |
|
|
456
|
+
| `DOMAIN\mike` | `domain-mike` |
|
|
457
|
+
| `Alice Smith` | `alice-smith` |
|
|
458
|
+
| `.hidden` | `hidden` |
|
|
459
|
+
| `mike.` | `mike.` (valid key, unchanged) |
|
|
460
|
+
| `` (empty) | `undefined` (login: `user`) |
|
|
461
|
+
| `@@@` | `undefined` (login: `user`) |
|
|
462
|
+
|
|
463
|
+
Derivation is idempotent and every valid key is a fixed point. On the
|
|
464
|
+
proxy path, a folded subject that is itself a valid key adopts the
|
|
465
|
+
existing user with that key; a derived-key collision under login
|
|
466
|
+
auto-provisioning takes the next free suffix instead.
|
|
467
|
+
|
|
468
|
+
**Proxy uniqueness assumption (deployment requirement).** Proxy
|
|
469
|
+
identity matching is case-insensitive: the proxy's usernames are
|
|
470
|
+
assumed unique case-insensitively, so `Alice` and `alice` are the same
|
|
471
|
+
person. Authelia/LDAP satisfy this. On a proxy where they are distinct
|
|
472
|
+
accounts, `Alice` would resolve to `alice`'s account — including admin
|
|
473
|
+
rights. Verify your identity source satisfies this before enabling the
|
|
474
|
+
proxy method.
|
|
475
|
+
|
|
476
|
+
**Derived vs typed collisions.** When a derived key is already taken
|
|
477
|
+
(proxy auto-provisioning, login auto-provisioning), the next free
|
|
478
|
+
suffix is chosen automatically: `alice`, then `alice-2`, `alice-3`,
|
|
479
|
+
…. Typed names — `sigrun user add`, the invite claim form, the
|
|
480
|
+
onboarding claim form — **refuse** with `username_taken` instead: an
|
|
481
|
+
admin choosing a name never gets silently suffixed.
|
|
482
|
+
|
|
483
|
+
**Login rule.** A new login user with no username claim derives from
|
|
484
|
+
the **full email** (`mike@example.com` → `mike_example.com`), never
|
|
485
|
+
just the local part. Existing linked users are unchanged — links are
|
|
486
|
+
matched by exact subject, not by re-deriving the key.
|
|
487
|
+
|
|
488
|
+
**Recipes.** Pre-provision a proxy user (and optionally grant admin):
|
|
489
|
+
|
|
490
|
+
```sh
|
|
491
|
+
sigrun user add alice --proxy Alice --admin
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
Link an additional proxy identity to an existing user:
|
|
495
|
+
|
|
496
|
+
```sh
|
|
497
|
+
sigrun user link alice --proxy alice.smith
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**Crash-orphan repair.** If the process crashed between writing the
|
|
501
|
+
user row and writing the proxy link, the user exists but cannot
|
|
502
|
+
resolve. The boot sweep logs one line per orphan:
|
|
503
|
+
|
|
504
|
+
```
|
|
505
|
+
identity: proxy user "alice-2" has no proxy link; repair with: sigrun user link alice-2 --proxy <username>
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Choose the repair that matches the intended owner:
|
|
509
|
+
|
|
510
|
+
- If the orphaned `-2` user should own the identity, run the printed
|
|
511
|
+
`sigrun user link <key> --proxy <username>` command.
|
|
512
|
+
- If the correct account already exists, delete the duplicate as an
|
|
513
|
+
admin with `DELETE /v1/users/alice-2?transferTo=alice`, where
|
|
514
|
+
`transferTo` names that existing account and receives its transferable
|
|
515
|
+
resources.
|
|
516
|
+
|
|
517
|
+
These are alternatives, not a sequence: deleting a user also removes
|
|
518
|
+
its links, so linking and then deleting the same `-2` user would undo
|
|
519
|
+
the repair.
|
|
520
|
+
|
|
314
521
|
### External sign-in (OIDC and OAuth 2)
|
|
315
522
|
|
|
316
523
|
The web sign-in screen lists configured external providers above the token
|
|
@@ -324,9 +531,9 @@ needed. Set `"builtinExtensions": {"oauth": false}` to disable it; like the
|
|
|
324
531
|
other built-in toggles, this is restart-required. A configured extension
|
|
325
532
|
whose package name is also `@sigrun/oauth` replaces the built-in. If the
|
|
326
533
|
built-in cannot be resolved or loaded, it is quarantined without aborting
|
|
327
|
-
boot.
|
|
328
|
-
|
|
329
|
-
|
|
534
|
+
boot. Standalone installation outside the built-in is not a supported use
|
|
535
|
+
case in 0.2; the package's type-only core dependency posture is accepted
|
|
536
|
+
for this release. It is inert when its settings contain no valid providers.
|
|
330
537
|
|
|
331
538
|
Create an OAuth/OIDC client at the identity service, with the redirect URI
|
|
332
539
|
shown below. Configure providers in the extension's
|
|
@@ -462,6 +669,20 @@ admin) or by trusted-proxy auto-provision; admins can transfer or remove
|
|
|
462
669
|
users (`PATCH`/`DELETE /v1/users/{user}` — deletion transfers their
|
|
463
670
|
conversations).
|
|
464
671
|
|
|
672
|
+
**Proxy-only onboarding.** On a proxy-only server bound beyond
|
|
673
|
+
loopback, onboarding happens entirely **through the proxy**: the first
|
|
674
|
+
claim and every later sign-in arrive as trusted proxy identities, no
|
|
675
|
+
setup or invite codes apply (no setup code is minted, and an invite
|
|
676
|
+
code cannot be redeemed without a vouch), and an unvouched
|
|
677
|
+
account-creating request is refused with 403
|
|
678
|
+
`proxy_identity_required`. A browser reaching sigrun without a trusted
|
|
679
|
+
proxy identity sees a ProxyUnidentified screen instead of a token or
|
|
680
|
+
setup-code form. As a deliberate, bounded exception,
|
|
681
|
+
`/v1/auth/callback/:provider` still lets a login provider with
|
|
682
|
+
`policy.autoProvision` create its own non-admin account on a proxy-only
|
|
683
|
+
server, although the resulting session cannot authenticate because the
|
|
684
|
+
token method is off.
|
|
685
|
+
|
|
465
686
|
**Sharing.** Conversations are private to their owner by default. The
|
|
466
687
|
owner can share one — household-wide or with named users and groups,
|
|
467
688
|
`read` or `write` — through the web UI's ⋯ menu; `write`
|
|
@@ -556,8 +777,72 @@ identity-switch capabilities once (replace `<helper>` with its path):
|
|
|
556
777
|
sudo setcap cap_setuid,cap_setgid+ep <helper>
|
|
557
778
|
```
|
|
558
779
|
|
|
559
|
-
The helper's boot self-test verifies the switch.
|
|
560
|
-
|
|
780
|
+
The helper's boot self-test verifies the switch. `SIGRUN_SANDBOX_HELPER`
|
|
781
|
+
points sigrun at a helper binary at a non-default absolute path (it falls back
|
|
782
|
+
to the installed location with one warning if the path does not exist), which is
|
|
783
|
+
how a staged copy gets used.
|
|
784
|
+
|
|
785
|
+
File capabilities only take effect when the capabilities they grant are
|
|
786
|
+
already in the **caller's** bounding set: executing the capped helper needs
|
|
787
|
+
`CAP_SETUID` and `CAP_SETGID` present in the process that launches it —
|
|
788
|
+
`CAP_SETFCAP` alone only permits writing the xattr and is not enough. A root
|
|
789
|
+
shell, or a host that runs sigrun as root and maps users to real OS accounts,
|
|
790
|
+
normally satisfies this.
|
|
791
|
+
|
|
792
|
+
This mapping is bare-metal only. The container entrypoint starts as the image's
|
|
793
|
+
non-root `USER` and execs straight through (one uid for the whole container), so
|
|
794
|
+
it holds no identity-switch capabilities to inherit — containers use the
|
|
795
|
+
Landlock jail alone, which is where container multi-user isolation comes from.
|
|
796
|
+
A root container start (`SIGRUN_UID=0`) does exist, but it is a mount-point
|
|
797
|
+
ownership trampoline, not an `osUsers` enabler: it needs
|
|
798
|
+
`CAP_CHOWN`/`CAP_SETUID`/`CAP_SETGID` for the chown-and-drop and still leaves
|
|
799
|
+
you with a single container uid.
|
|
800
|
+
|
|
801
|
+
#### If you insist on `osUsers` in a container — and why you shouldn't
|
|
802
|
+
|
|
803
|
+
It is possible, and two of the three pieces need no image change. A capped
|
|
804
|
+
helper can be staged at runtime on any writable path (a named volume, a
|
|
805
|
+
`tmpfs`, a bind mount), and the caps come from the container's own flags:
|
|
806
|
+
|
|
807
|
+
```yaml
|
|
808
|
+
# the runtime half — no derived image required
|
|
809
|
+
services:
|
|
810
|
+
sigrun:
|
|
811
|
+
user: "1000:1000"
|
|
812
|
+
cap_add: [SETUID, SETGID] # bounding set for the helper's file caps
|
|
813
|
+
volumes:
|
|
814
|
+
- sigrun-data:/data
|
|
815
|
+
- helper:/opt/helper # a writable path for the capped copy
|
|
816
|
+
# then, once per volume: copy the helper in, chmod 755, setcap
|
|
817
|
+
# cap_setuid,cap_setgid+ep under --cap-add SETFCAP, and point
|
|
818
|
+
# SIGRUN_SANDBOX_HELPER at it
|
|
819
|
+
security_opt:
|
|
820
|
+
- no-new-privileges:false # REQUIRED — see below
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
The blocker is the third piece: **`osUser` maps to a login name**, resolved from
|
|
824
|
+
`/etc/passwd`, so every user you want needs an account. The image ships exactly
|
|
825
|
+
two non-root accounts (`node` and `nobody`). That is what forces either a
|
|
826
|
+
derived image (`RUN useradd …` per user) or mounting a `passwd` file over
|
|
827
|
+
`/etc/passwd` through a `subPath`, which is fragile and surprises tooling.
|
|
828
|
+
|
|
829
|
+
And the default posture actively prevents it, three ways: `read_only: true`
|
|
830
|
+
makes `setcap` on the image layer fail with "Read-only file system",
|
|
831
|
+
`cap_drop: ALL` grants nothing, and `no-new-privileges: true` suppresses the
|
|
832
|
+
file-capability gain on `execve` even when `SETUID`/`SETGID` are in the bounding
|
|
833
|
+
set (the helper dies at its first privileged call). Enabling this therefore
|
|
834
|
+
means adding capabilities **and** permitting privilege escalation — a
|
|
835
|
+
deliberate threat-model relaxation, not a configuration tweak.
|
|
836
|
+
|
|
837
|
+
The reason not to is structural rather than configurational: inside one
|
|
838
|
+
container every `osUser` shares **one filesystem and one mount namespace**. You
|
|
839
|
+
would gain per-process uids and Landlock's per-process confinement, but not the
|
|
840
|
+
kernel-level user separation a host provides — because there is only one
|
|
841
|
+
container boundary to separate. You would be paying a real security cost (an
|
|
842
|
+
identity-switch capability held by the main process, privilege escalation
|
|
843
|
+
permitted) for isolation the container boundary already substantially provides.
|
|
844
|
+
Use the Landlock jail alone in containers; use `osUsers` on bare metal, where
|
|
845
|
+
the accounts and the separation are real.
|
|
561
846
|
|
|
562
847
|
### Kernel integration runner controls
|
|
563
848
|
|
|
@@ -790,7 +1075,7 @@ a dashboard) are in
|
|
|
790
1075
|
|
|
791
1076
|
## Built-in extensions
|
|
792
1077
|
|
|
793
|
-
|
|
1078
|
+
Five extensions are built into core — **codemode**, **MCP**, **tool
|
|
794
1079
|
search**, **gateway**, and **OAuth login**. The first three mirror
|
|
795
1080
|
what pi 1.3.0 ships built-in; the gateway is sigrun's own channel-adapter
|
|
796
1081
|
engine; OAuth provides OIDC, GitHub, and Discord login providers. They
|
|
@@ -833,6 +1118,11 @@ default. They join the offered set when an enabled MCP server's
|
|
|
833
1118
|
The MCP servers themselves live in the MCP config file — the
|
|
834
1119
|
`@sigrun/ext-mcp` package's README documents its format, including each
|
|
835
1120
|
server's `exposure` and the `SIGRUN_MCP_CONFIG` override.
|
|
1121
|
+
**User-supplied MCP servers are remote-only in 0.2** (URL transport);
|
|
1122
|
+
a user-supplied stdio server fails loudly with a config error. Dynamic
|
|
1123
|
+
jailed per-user stdio services are a post-release feature — per-user
|
|
1124
|
+
services are declared statically by extensions (see
|
|
1125
|
+
docs/extending.md).
|
|
836
1126
|
|
|
837
1127
|
```jsonc
|
|
838
1128
|
{
|
|
@@ -988,6 +1278,34 @@ launcher) is not supervised either; there the callout says "Restart
|
|
|
988
1278
|
sigrun to apply" with no button. `GET /v1/meta` reports the posture
|
|
989
1279
|
(`supervised`).
|
|
990
1280
|
|
|
1281
|
+
## Parked tasks
|
|
1282
|
+
|
|
1283
|
+
A task cut off repeatedly without progress (a crash loop) is parked by
|
|
1284
|
+
pi-durable's restart limit: it shows `blocked` with reason
|
|
1285
|
+
`restart_limit` and does not run again until an administrator retries
|
|
1286
|
+
it. The `SigrunTaskParked` alert fires on this. Two admin-only
|
|
1287
|
+
endpoints inspect and recover parked tasks:
|
|
1288
|
+
|
|
1289
|
+
- `GET /v1/admin/tasks?state=blocked` — lists blocked tasks with
|
|
1290
|
+
`{id, kind, reason, conversationId, owner?, extension?}` per row
|
|
1291
|
+
(owner is the conversation's session owner when it has one; extension
|
|
1292
|
+
is the registered task definition's owner when known).
|
|
1293
|
+
- `POST /v1/admin/tasks/:id/retry` — re-runs a restart-parked task:
|
|
1294
|
+
204 on success, 404 `unknown_task` for an unknown id, 409
|
|
1295
|
+
`not_parked` for a task that isn't parked (including one blocked for
|
|
1296
|
+
another reason, such as `missing_task`). A retried schedule job's
|
|
1297
|
+
status returns to `waiting` as the task runs again.
|
|
1298
|
+
|
|
1299
|
+
```sh
|
|
1300
|
+
# List blocked tasks (admin token).
|
|
1301
|
+
curl -H "Authorization: Bearer $TOKEN" \
|
|
1302
|
+
"http://localhost:3000/v1/admin/tasks?state=blocked"
|
|
1303
|
+
|
|
1304
|
+
# Retry a parked task.
|
|
1305
|
+
curl -X POST -H "Authorization: Bearer $TOKEN" \
|
|
1306
|
+
http://localhost:3000/v1/admin/tasks/7/retry
|
|
1307
|
+
```
|
|
1308
|
+
|
|
991
1309
|
## API sketch
|
|
992
1310
|
|
|
993
1311
|
- `GET /v1/meta` — version, extensions, health, auth posture
|
|
@@ -997,6 +1315,8 @@ sigrun to apply" with no button. `GET /v1/meta` reports the posture
|
|
|
997
1315
|
differs from boot) and PATCH reports `{applied, pending}`.
|
|
998
1316
|
- `POST /v1/admin/restart` — graceful restart (admin, supervised
|
|
999
1317
|
deploys only; see Restarting).
|
|
1318
|
+
- `GET /v1/admin/tasks?state=blocked`, `POST /v1/admin/tasks/{id}/retry`
|
|
1319
|
+
— parked-task inspection and recovery (admin; see Parked tasks).
|
|
1000
1320
|
- `GET /v1/jobs`, `POST /v1/jobs`, `PATCH`/`DELETE /v1/jobs/{id}` —
|
|
1001
1321
|
the jobs surface (see [Jobs](#jobs)); `POST /v1/jobs/{id}/run` fires
|
|
1002
1322
|
now; `GET /v1/jobs/{id}/runs` and `GET /v1/jobs/{id}/revisions` are
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"algorithm": "sha256",
|
|
3
|
+
"sources": {
|
|
4
|
+
"shared/src/blocks/index.ts": "ca37dbb56a4a1a05a40a0125a06d864b9a0671c70817c83a44dd0e3962999e30",
|
|
5
|
+
"src/blocks/builders.ts": "a0c9835aaeab871bc2548d4b8d4426849c60cdb0cb1b20142d3bbe11e8377005",
|
|
6
|
+
"src/blocks/images.ts": "2e1bd54546c9c1c5bf0cfe9b488aaffd7c37979ef84bae9789168275e63e202f",
|
|
7
|
+
"src/blocks/index.ts": "8878a2e2269572ebdecca2cf3b95fa67f144232d8a8fe4258b120948064d0520",
|
|
8
|
+
"src/blocks/limits.ts": "1e913f29167114e26bed6f8c1fd04c64b119ee1db3f4e9e2ae161ddf70578683",
|
|
9
|
+
"src/blocks/placements.ts": "fccda42669713d91dc78d025268ee127f926891cf383727c1e235a39b9f15c6f",
|
|
10
|
+
"src/blocks/schema.ts": "27dbc5cdf1152a16a75bfb1a70383f1a456999a41d393308c05079b41f087a83",
|
|
11
|
+
"src/blocks/validate.ts": "31b9fc78f569cceff229bd1f28bfc62e2f8da437684100e051104f059a1ca19f"
|
|
12
|
+
}
|
|
13
|
+
}
|