fix(tasks): validate owner identity and brand session ids
This commit is contained in:
11 files changed
+77
-29
No files matched your search
@@ -21,7 +21,9 @@ interface TaskStart {
|
||||
/**
|
||||
* The spawning agent. Its `session.header.id` becomes the task's owner
|
||||
* token (read/kill/wait/list are fenced to that session), and its disposal
|
||||
* cancels and awaits the task through the `ctx.agents.onCleanup` seam.
|
||||
* cancels and awaits the task through the `ctx.agents.onCleanup` seam. It
|
||||
* must be the exact live instance currently registered under its agent id;
|
||||
* a stale object whose id has been reused is rejected before work starts.
|
||||
* `undefined` starts an UNOWNED task: open to any caller, alive until the
|
||||
* tasks service disposes.
|
||||
*/
|
||||
@@ -86,7 +88,7 @@ interface TaskOutcome {
|
||||
|
||||
## What consumers see: `TaskSnapshot` and `TaskRead`
|
||||
|
||||
Snapshots are fresh projections, never live registry state. `reported` is the notice-suppression flag: the completion-notice injector (`dsh-tool-tasks`) skips a task whose terminal state the model already saw.
|
||||
Snapshots are fresh projections, never live registry state. `ownerSession` retains the shared branded `SessionId` type across the package boundary. `reported` is the notice-suppression flag: the completion-notice injector (`dsh-tool-tasks`) skips a task whose terminal state the model already saw.
|
||||
|
||||
```ts type-equiv
|
||||
interface TaskSnapshot {
|
||||
@@ -100,9 +102,10 @@ interface TaskSnapshot {
|
||||
* The owner's session id (`session.header.id`), for surfaces that must
|
||||
* reach the owning agent (the completion-notice injector); absent for
|
||||
* unowned tasks. Session ids are runtime-shared identifiers, not secrets —
|
||||
* the read/kill/wait/list FENCE is what isolation rests on.
|
||||
* the read/kill/wait/list FENCE is what isolation rests on. The shared
|
||||
* {@link SessionId} brand is preserved across this package boundary.
|
||||
*/
|
||||
ownerSession?: string
|
||||
ownerSession?: SessionId
|
||||
/** Current lifecycle state. */
|
||||
status: TaskStatus
|
||||
/** Kind-specific status detail, present once the producer supplied one (usually terminal). */
|
||||
@@ -137,4 +140,4 @@ interface TaskRead {
|
||||
|
||||
## The service
|
||||
|
||||
`TaskService` (`ctx.tasks` — [`packages/tasks/tasks/src/index.ts`](../../packages/tasks/tasks/src/index.ts)): `start` (preflight → producer `run()` → atomic commit, fenced by `attachSurface`), non-consuming `get`/`list` (caller-scoped — owned-by-caller plus unowned only), `read` (consuming for stream kinds), `kill` (producer `cancel` first; a throw leaves the task untouched), `wait` (bounded, abort cancels the wait only), and `onTaskDone` (a `TaskDoneListener` per terminal record, effect-scoped, contained). Every read/kill/wait/get compares the task's owner session with the caller's and rejects a foreign one. Owned tasks are cancelled and normally awaited to producer quiescence when their owning agent disposes (the `ctx.agents.onCleanup` seam); a teardown cancel that throws force-fails only the registry record and reports that the underlying work may be orphaned, preventing disposal deadlock without claiming quiescence. The model-facing surface over all of this is [dsh-tool-tasks](../../packages/tasks/tool-tasks/README.md).
|
||||
`TaskService` (`ctx.tasks` — [`packages/tasks/tasks/src/index.ts`](../../packages/tasks/tasks/src/index.ts)): `start` (preflight → producer `run()` → atomic commit, fenced by `attachSurface`), non-consuming `get`/`list` (caller-scoped — owned-by-caller plus unowned only), `read` (consuming for stream kinds), `kill` (producer `cancel` first; a throw leaves the task untouched), `wait` (bounded, abort cancels the wait only), and `onTaskDone` (a `TaskDoneListener` per terminal record, effect-scoped, contained). Start validates that an owned task names the exact live Agent instance currently registered under its id, so an old reference cannot bind work to a replacement agent's cleanup after id reuse. Every read/kill/wait/get separately compares the task's owner session with the caller's and rejects a foreign one. Owned tasks are cancelled and normally awaited to producer quiescence when their owning agent disposes (the `ctx.agents.onCleanup` seam); a teardown cancel that throws force-fails only the registry record and reports that the underlying work may be orphaned, preventing disposal deadlock without claiming quiescence. The model-facing surface over all of this is [dsh-tool-tasks](../../packages/tasks/tool-tasks/README.md).
|
||||
Reference in New Issue
Block a user