Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions greenfield/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 30 additions & 1 deletion greenfield/docs/architecture/greenfield-rewrite/progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ closes a phase; dated entries below provide the evidence, not a second status so
| 0 — Evidence and qualification | Complete | All eight mandatory spikes pass on exact Bun revision `17d6843606d76620cb55d31424d7fb0aed51c367`: build, transport, cross-process SQLite/outbox, Drizzle/Bun SQLite, browser data, chat batching, shutdown, and capped resources. Source-derived parity and the OpenClaw source audit pass as additional evidence. |
| 1 — Foundation | Complete | The self-contained future root builds immutable browser/web/worker artifacts, protects project-local production state, installs exact Bun and systemd artifacts, migrates a database copy, atomically promotes the release/database pair, serves readiness/browser assets, writes project-local logs, and proves crash-safe rollback and shutdown in a disposable lifecycle. |
| 2 — Trust and transport | Complete for the stated server scope | Authentication, MFA, WebAuthn, automation credentials, audit, authenticated renewable SSE, one-shot native Gateway bootstrap verification, and the consolidated [threat model](../../security/greenfield-phase-two-threat-model.md) have executable evidence. Browser UI and production cutover remain later gates. |
| 3 — Core operator domains | Started | Monitoring transaction/schema foundations exist; task, agent, report, incident, notification, schedule/job, cache/metrics procedures and browser parity are not complete. |
| 3 — Core operator domains | Started | The task domain and `/tasks` parity slice are implemented with durable history, realtime invalidation, and browser workflows. Agent, report, incident, notification, schedule/job, cache/metrics, overview, and worker-domain parity remain open. |
| 4 — Gateway and chat | Not started | The Phase 2 verifier is one-shot only. Persistent native Gateway lifecycle, current-protocol re-audit, sessions, chat journal/recovery, attachments, and frontend remain open. |
| 5 — Privileged and external domains | Not started | Worker-owned file/media, Docker, database, OpenClaw, GitHub, deployment, backup, and other privileged adapters remain open. |
| 6 — Parity, hardening, and cutover | Not started | Full UI parity, generated `/docs`, load/resource/restore evidence, cutover rehearsal, fresh production database, and legacy removal remain open. |
Expand Down Expand Up @@ -782,3 +782,32 @@ closes a phase; dated entries below provide the evidence, not a second status so

This completes Phase 1 only. Phase 3–6 domains, persistent Gateway/chat, privileged adapters,
full-browser parity, production rehearsal, cutover, and legacy deletion remain open.

### 2026-08-07 — Phase 3 task domain and browser slice

- A normalized task aggregate now owns tasks, canonical labels, optional automation profiles,
progress updates, and an append-only task-event history. Immediate admitted transactions keep
every aggregate mutation, audit record, and realtime outbox event atomic; version checks reject
stale edits and status movement without replaying a started callback.
- Eleven typed task procedures cover list/detail, create/update/delete, assign/move, and progress
add/update/delete/list. Effect services preserve typed domain failures, Valibot validates every
boundary and persisted record, capability policy separates task reads from writes, and task
mutations publish bounded realtime invalidations.
- Mira-relevant task events also create one redacted `task_notification_outbox` intent in the same
transaction. The queue preserves legacy create/update/assignment/movement/progress/deletion
semantics, suppresses `openclaw-task-tracking` self-notifications, hides task titles from other
automations, labels retained task fields as untrusted data, and uses the task-event ID as the
stable Gateway idempotency key. The Effect worker claims one delivery per lease, aborts a stalled
send before its lease can expire, and only acknowledges or releases work while it still owns a
live lease. No greenfield process is activated in production before final cutover, and that
cutover remains gated on composing the Phase 4 persistent authenticated Gateway client rather
than reusing the one-shot bootstrap verifier. Task intents therefore cannot accumulate in
production without their consumer.
- `/tasks` provides the reviewed four-column operator layout, server-side search and
assignee/recurring filters, accessible create/edit/detail/progress dialogs, and status movement
through `@dnd-kit/react`. Shared Headless UI controls, TanStack Form, TanStack Query, and the
existing reusable Dashboard presentation components own browser behavior rather than local
control implementations.
- The reviewed parity inventory now marks the 11 task operations and `/tasks` route implemented.
This closes only the task portion of Phase 3. Agent, report, incident, notification, job,
monitoring API, overview, cache/metrics, and real worker execution remain explicit gates.
2 changes: 0 additions & 2 deletions greenfield/docs/generated/packages-and-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
| Package | Declared | Resolved | Scope |
| --- | --- | --- | --- |
| `@daypicker/react` | `10.0.1` | `10.0.1` | runtime |
| `@dnd-kit/core` | `^6.3.1` | `6.3.1` | runtime |
| `@dnd-kit/react` | `^0.5.0` | `0.5.0` | runtime |
| `@dnd-kit/sortable` | `^10.0.0` | `10.0.0` | runtime |
| `@headlessui/react` | `^2.2.10` | `2.2.10` | runtime |
| `@microlink/react-json-view` | `^1.31.28` | `1.31.28` | runtime |
| `@simplewebauthn/browser` | `13.3.0` | `13.3.0` | runtime |
Expand Down
13 changes: 12 additions & 1 deletion greenfield/docs/generated/procedures.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@
| `automationSecurity.replaceCapabilities` | mutation | automation-security | MFA enrollment required; recent MFA when enabled | [input](./schemas/automationSecurity.replaceCapabilities.input.schema.json) | [output](./schemas/automationSecurity.replaceCapabilities.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | `mfa_enrollment_required`, `step_up_required` | Atomically replaces a principal's least-privilege capability set. |
| `automationSecurity.revokeCredential` | mutation | automation-security | MFA enrollment required; recent MFA when enabled | [input](./schemas/automationSecurity.revokeCredential.input.schema.json) | [output](./schemas/automationSecurity.revokeCredential.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | `mfa_enrollment_required`, `step_up_required` | Explicitly revokes one automation credential after client cutover. |
| `automationSecurity.rotateCredential` | mutation | automation-security | MFA enrollment required; recent MFA when enabled | [input](./schemas/automationSecurity.rotateCredential.input.schema.json) | [output](./schemas/automationSecurity.rotateCredential.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `PRECONDITION_FAILED`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | `mfa_enrollment_required`, `step_up_required` | Stages a linked replacement credential without revoking its predecessor. |
| `events.stream` | subscription | events | Authenticated; per-topic: notifications:read, reports:read | [input](./schemas/events.stream.input.schema.json) | [output](./schemas/events.stream.output.schema.json) | `BAD_REQUEST`, `FORBIDDEN`, `SERVICE_UNAVAILABLE`, `TOO_MANY_REQUESTS`, `UNAUTHORIZED` | None | Streams authorized durable changes with tracked resume cursors. |
| `events.stream` | subscription | events | Authenticated; per-topic: notifications:read, reports:read, tasks:read | [input](./schemas/events.stream.input.schema.json) | [output](./schemas/events.stream.output.schema.json) | `BAD_REQUEST`, `FORBIDDEN`, `SERVICE_UNAVAILABLE`, `TOO_MANY_REQUESTS`, `UNAUTHORIZED` | None | Streams authorized durable changes with tracked resume cursors. |
| `securityAudit.listEvents` | query | securityAudit | Authenticated browser session | [input](./schemas/securityAudit.listEvents.input.schema.json) | [output](./schemas/securityAudit.listEvents.output.schema.json) | `FORBIDDEN`, `UNAUTHORIZED` | None | Lists redacted immutable security events in stable newest-first order. |
| `system.runtimeIdentity` | query | system | Public | [input](./schemas/system.runtimeIdentity.input.schema.json) | [output](./schemas/system.runtimeIdentity.output.schema.json) | None | None | Returns the Bun runtime identity of the serving process. |
| `tasks.addUpdate` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.addUpdate.input.schema.json) | [output](./schemas/tasks.addUpdate.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Appends one authenticated progress update to a task. |
| `tasks.assign` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.assign.input.schema.json) | [output](./schemas/tasks.assign.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Assigns or unassigns a task under optimistic concurrency control. |
| `tasks.create` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.create.input.schema.json) | [output](./schemas/tasks.create.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Creates one task with server-owned identity and audit history. |
| `tasks.delete` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.delete.input.schema.json) | [output](./schemas/tasks.delete.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Deletes a version-matched task and mutable relationships while retaining append-only events. |
| `tasks.deleteProgress` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.deleteProgress.input.schema.json) | [output](./schemas/tasks.deleteProgress.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Deletes one version-matched task progress entry. |
| `tasks.get` | query | tasks | Authenticated: tasks:read | [input](./schemas/tasks.get.input.schema.json) | [output](./schemas/tasks.get.output.schema.json) | `FORBIDDEN`, `NOT_FOUND`, `UNAUTHORIZED` | None | Loads one complete task for detail editing. |
| `tasks.list` | query | tasks | Authenticated: tasks:read | [input](./schemas/tasks.list.input.schema.json) | [output](./schemas/tasks.list.output.schema.json) | `FORBIDDEN`, `UNAUTHORIZED` | None | Lists one stable filtered page of task-board rows. |
| `tasks.listUpdates` | query | tasks | Authenticated: tasks:read | [input](./schemas/tasks.listUpdates.input.schema.json) | [output](./schemas/tasks.listUpdates.output.schema.json) | `FORBIDDEN`, `NOT_FOUND`, `UNAUTHORIZED` | None | Lists one stable newest-first page of task progress entries. |
| `tasks.move` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.move.input.schema.json) | [output](./schemas/tasks.move.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Moves a task between board columns under optimistic concurrency control. |
| `tasks.update` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.update.input.schema.json) | [output](./schemas/tasks.update.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Updates task content under optimistic concurrency control. |
| `tasks.updateProgress` | mutation | tasks | Authenticated: tasks:write | [input](./schemas/tasks.updateProgress.input.schema.json) | [output](./schemas/tasks.updateProgress.output.schema.json) | `CONFLICT`, `FORBIDDEN`, `NOT_FOUND`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED` | None | Edits one task progress entry under optimistic concurrency control. |
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"id": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"createdAtMs": {
Expand Down Expand Up @@ -145,11 +147,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"createdAtMs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"createdAtMs": {
Expand Down Expand Up @@ -94,11 +96,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"createdAtMs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"createdAtMs": {
Expand Down Expand Up @@ -119,11 +121,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
},
"createdAtMs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
"items": {
"enum": [
"notifications:read",
"reports:read"
"reports:read",
"tasks:read",
"tasks:write"
],
"type": "string"
},
"maxItems": 2,
"maxItems": 4,
"uniqueItems": true
}
},
Expand Down
Loading