feat: implement OpenBot collaboration backlog - #1
Merged
Conversation
Record successful code, PostgreSQL and Compose evidence for FND-01, AUTH-01 and WS-01; resume the approved dependency graph from WS-02 and PROV-01. Source local commit: 027b6afa2dc0a03313d2357a2710ca88e1fe2501 Source tree: 81127ed
|
Add owner-scoped connection settings and APIs, live text/action probes, authenticated credential encryption, destination policy with pinned DNS, bounded redacted evidence, optimistic writes, audits and runtime database grants. Verified locally: formatting/types, 145 unit/integration tests, 6 browser scenarios, API/Web builds, and independent standards/spec reviews with regression fixes. Actual PostgreSQL/Compose evidence remains tracked as PROV-01-E1 pending this PR's CI. Source local commit: f5a5c71f01860a79dfeb5b0cf8f29cb099b95ccd Source tree: aed2091
… checks Add invitation management and joining for new and existing users, with atomic token consumption, audits and immediate authority checks. Fix the infrastructure PostgreSQL dependency found by CI. Verified locally: 186 unit/integration tests, 7 browser scenarios, formatting, types and production builds. Real PostgreSQL and Compose gates remain pending on this revision. Local commit: 014320d5261af8cf0c5e0a4158d135459936794d Verified Git tree: bb883a5
…tion Support persisted Responses selection, shared text/action events and normalized endpoint errors. Preserve cancellation and guarded transport, separate generation limits from diagnostic retention, and accept valid SSE line endings. Verified: 213 unit/integration tests, 7 browser scenarios, formatting, types and production builds. Independent standards and specification reviews passed. PostgreSQL/Compose checks must pass on this revision. Local commit: 42ff213a6196f2ea186b78a837226e6e70adb4c5 Verified Git tree: 57fbb8b
Add explicit Anthropic version and credential settings, live text and tool events, usage and stop normalization, and the shared guarded transport. Fix protocol-specific native form validation with witnessed browser regressions. Verified: 249 unit/integration tests, 8 browser scenarios, formatting, types and builds. Independent standards and specification reviews passed. Actual PostgreSQL and Compose must pass on this revision. Local commit: 980af1309f325061ca451621e569c18dd6668c6c Verified Git tree: 67851a9
Add scoped member listing, invitation provenance, owner/admin authority and transactional last-owner protection. Preserve account and session identity after removal while denying former-workspace access. Fix member and invitation BFF DELETE formatting and response-body deadlines. Verified: 284 unit/integration tests, 9 browser scenarios, formatting, types and builds; independent standards/spec reviews and deployment-smoke review passed. Real PostgreSQL and Compose gates remain pending on this revision. Local commit: 2baa1882dafddb2d7f30646bc351976eca24c56c Verified Git tree: 50dbae9
Support signed Authorization Code flows with PKCE, browser-bound single-use transactions, issuer-subject identities, explicit account linking and invitation-only registration. Add dedicated real IdP browser coverage and isolated restricted-role PostgreSQL CI. Verified: 352 unit/integration tests, 9 ordinary browser scenarios and one signed-IdP journey, formatting, types and builds. Independent standards/spec and integration-delta reviews passed. Workspace member PostgreSQL/Compose evidence is closed; OIDC external gates remain pending. Local commit: 8081ae9c77be585238d7c84247c8fd1d8fbe1600 Verified Git tree: f21c348
Separate workspace usage from credential administration, preserving personal credential encryption and canonical workspace identities. Recheck current authority and revisions before each probe generation and result write, retain disabled connection identities, and expose safe role-specific settings across all three protocols. Verified: 400 unit/integration tests, 10 ordinary browser scenarios and one signed-IdP journey, formatting, types and builds. Independent standards/spec and deployment-assertion reviews passed. Shared-provider PostgreSQL/Compose gates remain pending; OIDC runtime evidence is closed. Local commit: 1e1f6643d4a410667fc460c658bf1fc004143b91 Verified Git tree: 4fb37d3
Add group creation, metadata, discovery and owner/admin/member management. Require current workspace membership together with explicit group authorization, preserve historical authors and retained grants, and protect the last eligible owner. Add canonical UUID handling and genuine historical-schema migration fixtures. Verified: 445 unit/integration tests, 11 ordinary browser scenarios and one signed-IdP journey, formatting, types and builds. Independent standards/spec and new Compose lifecycle reviews passed. Shared-provider runtime gate is closed; group PostgreSQL/Compose gates remain pending. Local commit: 141369819bf53a2102ba2ccc3be06b55df0ec344 Verified Git tree: 2d959c6
…iness Add one-time token creation, hash-only storage, redacted management, public identity, fixed scopes, current-membership checks and permanent member-removal revocation. Preserve workspace-first locking and use fresh post-lock timestamps. Canonicalize member-removal audit references. Fix PostgreSQL readiness probes to require authenticated target-database TCP queries before migrations and legacy-volume seeding; cover temporary initialization, unavailable databases and seed-once behavior. Verified combined feature: 478 unit/integration tests, 12 ordinary browser scenarios plus one signed-IdP journey, types, formatting and builds. Follow-up audit/readiness changes: 31 focused tests, types, formatting and shell syntax checks. Independent feature and narrow-fix reviews passed. Actual API-token and group deployment gates remain pending. Local commit: e0213a5e7dd4997868d0fa07c6bbed98d00d0e43 Verified Git tree: fb90774
…k policies Add explicit capability evidence, attributable re-probes, justified manual overrides with persistent active/stale badges, target generation invalidation, optimistic revisions and safe audit snapshots. Validate same-scope fallback graphs atomically, preview deterministic current eligibility, and expose narrow transaction-scoped model binding admission. Add personal/workspace capability pages with permission-aware controls and explicit unavailable selections. Correct group deployment smoke to verify invited roles through the membership API, retaining all authorization/audit checks and safe failure diagnostics. Verified: 539 unit/integration tests, 14 ordinary browser scenarios plus one real signed-IdP journey, formatting, types with zero Web warnings, both builds and shell syntax. Independent standards/spec and integration-delta reviews passed. Group, API-token and capability PostgreSQL/Compose gates remain pending the full deployment retry. Local commit: f3d3671c2b3034c1d4d4e3224789643505ff7413 Verified Git tree: 514ec8f
Verified local snapshot 47553b1e5331aeaa869d44e96537b38d53d9fd2b; both review axes clean, 594 tests and 16 browser journeys passed. Add isolated PostgreSQL Bot validation and ordered Compose privileges.
Publish the independently reviewed BOT-04 integration with 651 passing tests and 18 browser scenarios. Keep native PostgreSQL and Compose validation as an explicit pending CI gate.
Publish independently reviewed BOT-02 integration: 704 tests and 19 browser scenarios pass. Preserve immutable historical references and add real PostgreSQL, private S3, and deployed image-runtime CI gates.
Integrate independently reviewed Bot copy and archive/restore/soft-delete flows. Preserve private configuration access, fixed recovery grace, actual-user model admission, immutable versions and retained avatar references. Accepted local source 6c98be0db757408d0c8a764197becdf5627f4f8f. Full integration verification: 969 unit/integration tests, 32 ordinary browser scenarios, one signed-OIDC journey, lint, typecheck and builds. Follow-up Compose expectation checks are scoped and native PostgreSQL/Compose evidence remains pending.
Publish reviewed API-02 integration and the isolated S3 case budget correction. Record 24 implemented tickets, 22 fully complete, with native public-Bot and large-file S3 gates explicit. Accepted local snapshot: e51fafe4f5de1e5f0f5b8e1f91dbbc93201143c8 Exact tree: 2bb6bd7
…nd scoped group memory Accepted local snapshot b5a744f7e8637168832f054e524f80af671a65be. Both independent review axes CLEAN; full verify: 1,453 unit/integration, 53 browser, one OIDC. Four actual PostgreSQL/Compose gates remain pending. Preserve all 67 tickets and 401 acceptance texts.
…utput Accepted local snapshot d0c8c34291c256fb78222322da37b8a2b61c591b. Full verify passed: 1504 nonbrowser, 60 browser and one OIDC tests. Add dedicated native cancellation and separate-worker Compose gates.
Accepted local snapshot c7dcdcb6b3848a89407c76664869f8290d0fe9c5. Temporarily validate the named backfill constraint before DDL; retain schema and guards. Check expired progress before durable partial writes and retain native rollback checks.
…backs Tighten automatic-retry eligibility to the closed COL-10 allowlist and add optional versioned retryPolicy plus same-scope fallbackBindings without rewriting historical Bot JSON. Co-authored-by: Dongsheng <Blackman99@users.noreply.github.com>
Schedule automatic same-Task continuations only for the closed transient failure allowlist, persist a single notBefore, and admit at most one successor without fabricating a retry command or registering migration 0024. Co-authored-by: Dongsheng <Blackman99@users.noreply.github.com>
Show previous and next protocol plus model, the closed failure reason, and whether the next model is only planned or already admitted, without connection, endpoint or credential fields. Co-authored-by: Dongsheng <Blackman99@users.noreply.github.com>
Complete remaining ROUT-01 AC2 public API mutations with groups:write, workspace-authority locking before routine FOR UPDATE, and token admit recheck. UI, trigger, recovery, uniqueness, and bot-deny ACs stay open.
Add ROUT-01 AC3/AC5 (and cohesive AC4) slice: migration 0052_routine_occurrences enforces UNIQUE(routine_id, occurrence_key), RoutineExecutor claims due active routines on the task worker poll, creates exactly one standard collaboration task with the routine budget, links it for GET /v1/routines/:id, and recovers unexpired due work after restart without duplication. AC2 UI and AC6 bot-deny remain open.
Pin the Compose fresh-volume migration ledger assertion to 0052_routine_occurrences after the ROUT-01 occurrence uniqueness cut.
Complete ROUT-01 leftover ACs: session group routines API plus web create/edit/pause/resume/cancel pages, and explicit worker denial of bot create_routine and budget/frequency edit_routine collaboration actions. Leave ticket checkboxes unchecked for Tester.
Close ROUT-01 after tip 5ba2a2a, green Verify 34035394210, and Tester 6/6 PASS. Mark ROUT-02 ready-for-agent and DEPLOY-01 in-progress for the single-host Compose baseline.
DEPLOY-01 first TDD slice: OPENBOT_TELEMETRY defaults to false in .env.example and Compose, API/worker construct only a local no-op recorder, and idle API/worker smokes make no unnecessary outbound HTTP. Contract tests also lock undeclared postgres/worker host ports.
DEPLOY-01 second TDD slice for AC1–4: add a worker healthcheck, wait for a healthy API before starting web, and lock migrate-once, named-volume durability, and private-network model wiring in Compose/README contracts. AC5–6 remain Tester-proven; AC1–4 stay unchecked until live stack proof.
…ions Close ROUT-01 AC2's Web surface and AC6. Session routes back a group Routines page: list, create, edit, pause, resume and cancel reach the same RoutineService as /v1/routines, take the trusted web origin on every write, and require current group content authority. Schedules are entered as wall time in the routine's own IANA zone, so the browser's zone never moves an execution; a wall time skipped by a forward DST transition is refused before it reaches the API. AC6 is enforced twice. BOT_COLLABORATION_TOOL_NAMES pins the four tools a Bot is ever offered and offersRoutineTool keeps a routine capability out of that set, while the worker's closed action whitelist fails any routine-shaped action without touching the table. RoutineService also takes a RoutineActor origin: a Bot-attributed create is refused, as is a Bot-attributed edit that raises max_cost_micros, moves execute_at earlier, or extends expires_at. A Bot-attributed reduction still works. No new migration; the ledger tip stays 0052_routine_occurrences. ROUT-01 is stamped complete-with-external-verification. ROUT-01-E1 opens on REL-01 for the routine PostgreSQL cases under the restricted runtime role and the routines.spec.ts browser scenario: this host runs neither, because its bundled Chromium is a Linux binary and /bin/bash is 3.2. The page was instead verified against the built app over HTTP, 27/27 checks.
Close ROUT-02. Migration 0053_cron_routines adds routines.cron_expression, keeps kind and the expression consistent, and extends routine_occurrences.outcome with skipped_overlap. A cron routine reuses execute_at as its next occurrence and advances it on every tick, so the published due-work query and the 0052 occurrence-uniqueness guard are unchanged. The scheduler walks candidate wall times rather than instants and resolves each through the zone. That is what makes both daylight-saving transitions correct: an hour a forward transition removes has no instant and is stepped over, and an hour a backward transition repeats resolves to exactly one instant, so no occurrence is duplicated. Cron treats day-of-month and day-of-week as a union when both are narrowed. A tick whose prior task is not completed, failed or cancelled records skipped_overlap and creates nothing. A tick older than CRON_CATCH_UP_MS records routine.missed, backfills nothing, and resumes at the first occurrence after now. A routine with no occurrence left inside its window disables itself and creates no later task. Run history joins occurrences to their tasks, so completed, failed, cancelled, expired and skipped_overlap stay distinct. The group Routines page takes a schedule type, accepts a five-field expression, and shows the next execution, the latest result, and a bounded run history. A Bot-attributed cron change is refused with the other ROUT-01 AC6 escalations: relative frequency of two expressions is not decidable here. ROUT-02 is stamped complete-with-external-verification. ROUT-02-E1 opens on REL-01 for the cron PostgreSQL cases under the restricted runtime role and the cron browser scenario, which this host cannot run. The page was verified against the built app over HTTP: 28/28 one-time and 24/24 cron checks, covering zone conversion, overlap, catch-up, history and cancel.
Close NOTIF-01. Migration 0054_task_notifications stores one content-free pointer per recipient: who, which workspace event, and the group, conversation and task to open. No body, prompt, summary or title is copied, so an inbox row cannot disclose content the reader's authorization would refuse. Fan-out runs inside the producer's own transaction from publishWorkspaceTaskEvent, so a notification never outlives a rolled-back outcome and never lags the stream. UNIQUE (workspace_id, user_id, source_sequence) with ON CONFLICT DO NOTHING makes a retried producer and a replayed stream both idempotent. Cancellation and interim updates stay stream-only: the inbox covers pending approvals, completion, failure and exhausted budgets. A pending approval reaches every human member of the group that can answer it; a terminal or budget outcome reaches the person whose request was waiting. Reads are scoped to the caller's own rows, and opening asks the API to re-lock the referenced conversation before it returns a destination, so a notification kept from a group the reader has left leads nowhere. The Web inbox pages newest first from a createdAt|id cursor, marks one or all read, and updates live: the browser opens an EventSource against the web server, which forwards the session cookie to GET /v1/events, so no API credential reaches the page. Each frame triggers a fetch of a private JSON feed rather than trusting frame contents. NOTIF-01 is stamped complete-with-external-verification. NOTIF-01-E1 opens on REL-01 for the notification PostgreSQL cases under the restricted runtime role and the browser scenario, which this host cannot run. The inbox was verified against the built app over HTTP: 24/24 checks, plus a separate 6/6 live-delivery check that emits an event after the stream is already open.
Close NOTIF-02. Migration 0055_mention_notifications adds conversation_event_mentions, which keeps stable member ids beside the message.created event so a renamed member is still the recipient; group_notification_settings, one level per member per group; the mention inbox kind with a nullable task_id and a message_id; and the message.mention workspace event type, so an open inbox receives a mention live. A mention names a current human member of the group by id. A removed member, a stranger, or a Bot grant is refused before the message is written, so a refused mention stores nothing and no notification can carry group content to an unauthorized reader. The stream frame names only the conversation, message and event; recipients are computed from the stored mention rows inside the same transaction, and the author is never notified about their own mention. Fan-out reads membership and levels when the event is published, so a change applies to the next event and a member the group removed receives nothing new. all receives approvals, own-task outcomes and mentions; mentions_only receives direct mentions only; muted receives nothing from that group. Direct-Bot conversations have no group and are unaffected. Bot mentions remain the explicit Lead grant on a task submission and touch routing only. The Web message form offers a member multi-select for group conversations, the group page carries the member's own level, and the inbox opens a mention at its message anchor. NOTIF-02 is stamped complete-with-external-verification; NOTIF-02-E1 opens on REL-01 for the PostgreSQL cases under the restricted runtime role and the browser scenario, which this host cannot run. DATA-01 is now ready: both of its remaining blockers carry explicit REL-01 gates. The flow was verified against the built app over HTTP, 21/21 checks.
Blackman99
marked this pull request as ready for review
September 6, 2026 15:30
Close DATA-01. Migration 0056_workspace_exports stores one job row per export: status, attempt, schema version, object id, size, SHA-256, file count, manifest, error code and timestamps. Checks tie a completed export to an archive and strip an expired one of both object and manifest. The collector reads an explicit, workspace-scoped table allowlist and passes every row through SECRET_COLUMN_PATTERN, so credential, session, token, provider and key-material tables are never read and a secret-bearing column in any allowlisted table is dropped. Attachments are the only binary content, each read through the attachment store's own bound. A dependency-free ustar writer puts manifest.json first, with a size and SHA-256 for every file, and export.json names the schema version and creation time. The export worker runs on the task worker poll. Claiming is a queued to running transition, completion is guarded by the running status, and an orphaned second object is deleted rather than recorded, so repeated completion cannot produce conflicting state. A failure keeps the row with its error code and retry re-queues it as a fresh attempt. Archives are deleted 24 hours after completion while outcome, size, checksum and timestamps stay in the record and the workspace.export_* audit trail. Only workspace owners and administrators can create, list, inspect, retry or download; the Web settings page proxies the download so the session cookie never reaches the browser. DATA-01 is stamped complete-with-external-verification; DATA-01-E1 opens on REL-01 for the PostgreSQL cases under the restricted runtime role, the S3-compatible archive contract and the browser scenario, none of which this host can run. DATA-02 is now ready. The flow was verified against the built app over HTTP, 27/27 checks, including a parsed archive whose manifest checksums all match and which carries no credential sentinel.
Close DATA-02. Migration 0057_workspace_soft_deletion adds deleted_at, purge_after and deleted_by_user_id to workspaces with a consistency check; no other table changes, so content, attachments, memory and indexes stay untouched until the grace period ends and a later purge runs. Enforcement is central. lockWorkspaceAuthority, the authority every group, Bot, task, member, token, event, notification and export path takes, now selects only undeleted rows; the API-token authorization join and the session event-stream admission require an undeleted workspace; the session identity prefers live workspaces without locking a person out; the workspace list hides a deleted workspace from everyone but its owners; and a preHandler in buildApp refuses every workspace-scoped session route except the workspace record and the deletion routes. A member therefore loses the workspace at once through the UI, REST and SSE. WorkspaceLifecycleService locks the workspace row for every transition and writes conditionally, so repeated or concurrent deletes and restores converge on one state and only the first records an audit. Owners delete; owners or the instance administrator restore until purge_after, after which grace_period_ended is returned. The grace period is WORKSPACE_DELETION_GRACE_DAYS, default 30, in whole days. The Web confirmation page offers the data export first, shows the exact purge_after a deletion confirmed now would record, requires the typed workspace name, and an owner still sees the deleted workspace flagged with a way to restore it. DATA-02 is stamped complete-with-external-verification; DATA-02-E1 opens on REL-01 for the PostgreSQL cases under the restricted runtime role and the browser scenario, which this host cannot run. DATA-03 is now ready. The flow was verified against the built app over HTTP, 23/23 checks.
Close DATA-03, the expand phase of the purge. Migration 0058_workspace_purge_manifest adds a versioned manifest whose status becomes completed only when every step is recorded complete, and one step row per target table with the handler, handler version, estimated rows, deleted rows and outcome. The handler registry lists eleven versioned relational handlers with their tables in dependency order: notifications, routines, memory metadata, knowledge rows, tasks and runs, group membership and grants, messages, group rows, Bots, API tokens and the event stream. Every table is scoped by a predicate derived from the workspace id, directly or through a join to tasks, runs, conversations, groups, Bots, memories, candidates, intents or requests, so a handler can never reach a neighbouring workspace and running it twice deletes nothing new. dryRun counts with the same predicates and writes nothing. execute requires a workspace that is soft-deleted and past purge_after, rechecks that before every step so a restore stops it, reuses the latest unfinished manifest so a retry resumes after its completed steps, runs each table step in its own transaction, records a failed step with its error code, and never reports a partial run as complete. Nothing wires execute to a schedule or a route: enabling the irreversible purge is DATA-05, and object storage, caches and indexes are DATA-04. DATA-03 is stamped complete-with-external-verification; DATA-03-E1 opens on REL-01 for the native PostgreSQL run under real foreign keys, which this host cannot execute. DATA-04 is now ready.
Close DATA-04, the migrate phase of the purge. The DATA-03 manifest already records status, estimate, deleted rows and failure code per step, so no migration is needed: the manifest version moves to 2 and the registry gains object-backed steps. A step may name an object column and kind; the service reads the matched rows, deletes each object from the store for that kind with a key built from the workspace being purged and never from the row, treats a missing object as already deleted, and fails the step with a store_* code on any other store error, all before the row DELETE in the same step transaction. Handlers: attachments (attachment_objects.storage_id), avatars (bot_avatar_references, then avatar_objects by id), exports (workspace_exports.object_id) and connections (model_price_versions, then workspace_model_connections, whose sealed_credentials carries the wrapped key material), with the knowledge handler unchanged. This codebase keeps no separate summary store, vector index or cache; its only search index is the GIN full-text index on knowledge_chunks.text, which the knowledge row deletion empties. A purge whose object step has no configured store fails that step and deletes no rows. Fault injection proves every deleted key names the purged workspace, a mid-run store failure leaves completed deletions and the neighbour's objects intact, and a retry finishes what remains. DATA-04 is stamped complete-with-external-verification; DATA-04-E1 opens on REL-01 for the S3-compatible store and native PostgreSQL runs this host cannot execute. DATA-05 is now ready.
Close DATA-05, the contract phase of the purge. Migration 0059_workspace_retention_and_receipts adds the instance_settings singleton with workspace_retention_days (1 to 3650, seeded at 30) and workspace_purge_receipts, whose only key is a SHA-256 fingerprint of the workspace id. The instance administrator reads and changes the retention period through GET/PATCH /api/v1/instance/settings and the /app/instance page; every new deletion, and the confirmation page's preview, records purge_after from it. WorkspacePurgeService.finalize runs in one transaction: it re-locks the workspace row, requires deleted_at set and purge_after passed, requires the current-version manifest to be completed with no open step, aggregates per-handler counts, removes the manifest, invitations, memberships and the workspace row, and writes the receipt plus a workspace.purged audit that names only the fingerprint, the timestamps, who requested it, the result and the counts. Names, ids and content do not survive. RetentionWorker runs on the task worker poll: one soft-deleted workspace past its purge_after per tick, executing or resuming its manifest and finalizing only on completion; a workspace restored in the meantime is skipped by the eligibility checks inside the purge itself. Once purged, a workspace cannot be listed, exported, restored or read through the API or the event stream. The end-to-end test seeds messages, tasks, routines, notifications, memories, attachments, knowledge, avatars and provider connections in two workspaces, runs the scheduler, and proves the target is reduced to its receipt while the neighbour keeps every row and object. DATA-05 is stamped complete-with-external-verification; DATA-05-E1 opens on REL-01 for the native PostgreSQL and S3-compatible run this host cannot execute.
Add compose-baseline.test.ts, which parses compose.yaml and asserts the one-command layout: an internal data network with no PostgreSQL, migrate or worker host ports, API and web ports bound to OPENBOT_BIND_ADDRESS (loopback by default), a one-shot migrate service the API and worker depend on with service_completed_successfully, health gates, postgres-data and object-data volumes on both API and worker, the provider host/scheme/CIDR policy on both, read-only hardened containers, and no telemetry configuration anywhere. Add idle-outbound.test.ts, which instruments fetch, http.request and https.request while the API answers its status probe and the worker polls an empty queue, and asserts no outbound request is made. Add docs/deployment.md covering start, required secret changes, network exposure, persistence across restarts, private-network model endpoints and the telemetry position; link it from the README and note it in .env.example. Stamp DEPLOY-01 complete-with-external-verification with gate DEPLOY-01-E1 on REL-01, unblock DEPLOY-02 and PWA-01, and update the backlog index and frontier.
Add schema-compatibility.ts, which classifies a database's migration ledger against the migrations a build carries — current, unmigrated, behind (with the pending count), unsupported, ahead, or diverged (naming the first mismatch) — and phrases the operator's next step for each. The readiness probe returns the verdict as checks.schema whenever a reachable database is not current, so GET /api/v1/status answers 503 with the action while the ready-state JSON is unchanged; the task worker refuses to start with the same message. migrateDatabase refuses ahead and diverged ledgers with that message and now returns the versions it applied, which the migrate command prints. Pin the existing lock and atomicity with migration-lock.test.ts (advisory lock before the ledger read; a failure after three ledger writes ends in ROLLBACK with no COMMIT) and migration-lock-runtime.test.ts on PostgreSQL (a held lock blocks a second migrator until released). upgrade-path.test.ts migrates pg-mem to 0052_routine_occurrences, seeds a user with a real argon2 credential, their workspace, group and one message, proves the stale readiness and its message, upgrades through the fixture, then signs in with the old credential, reads the old group and message, creates a group and submits a task. The Compose job gains a step that inserts a future ledger row and requires the ahead refusal. Add docs/upgrade.md — backup first, supported versions, the upgrade steps, the post-upgrade smoke, readiness states and the recovery path — and link it from the README and docs/deployment.md. Fixtures accept an existing pool so a test can upgrade a pre-seeded database. Stamp DEPLOY-02 complete-with-external-verification with gate DEPLOY-02-E1 on REL-01, unblock DEPLOY-03, and update the backlog index and frontier.
Migration 0060_job_acquisition_pause adds an instance-wide pause to instance_settings; TaskWorker.runOnce checks it first, so no task, routine, extraction, export or purge work is acquired while a backup holds it. Add apps/api/src/backup: JobAcquisitionPause (pause, resume, running-job count); a format-1 manifest carrying the application version and build, the schema version and full migration ledger, per-table row counts, the retention setting and every object with its SHA-256, plus a strict parser and a compatibility check that requires the ledger to equal this build's; a tar archive (manifest.json, checksums.sha256, database.dump, objects/<ws>/<id>) whose reader verifies every hash and rejects missing, extra or disagreeing files before returning anything; BackupService, whose backup pauses acquisition, waits for running runs and exports up to an idle timeout, dumps, snapshots the object volume, writes the archive and resumes even on failure, and whose restore checks integrity, compatibility and an empty database and object volume before the first write, then loads the dump, applies the retention setting, writes objects without overwriting and re-counts and re-hashes everything the manifest recorded; and a CLI (backup, restore, inspect) that drives pg_dump --format=custom --data-only and pg_restore --data-only --disable-triggers --single-transaction. The master key is never read and the archive is asserted free of it. Add the profile-only backup Compose service with owner credentials, the object volume and ./backups, install postgresql17-client in the API image, and add a Compose job step that backs up the populated stack, refuses a restore into it, recreates the stack from empty volumes, restores, requires consistency.ok and compares row and object counts. Add docs/backup-restore.md; point docs/upgrade.md, docs/deployment.md and the README at the tool. Stamp DEPLOY-03 complete-with-external-verification with gate DEPLOY-03-E1 on REL-01 and update the backlog index and frontier.
Add the web manifest (standalone, /app start URL, SVG plus 192/512 PNG and a maskable icon) and link it, the theme colour, colour scheme and icons from app.html. Add an online-first service worker that caches only build assets, static files and the /offline page, serves shell assets from cache, sends every navigation and API request to the network, never caches /api, streams, feeds or downloads, and answers an unreachable navigation or submitted form with the offline page at status 503 so no write is ever presented as successful. Add a root layout with a skip link to a focusable content target, an online/offline status banner, always-visible focus outlines and phone-width rules (tables scroll inside their box, headers wrap, main padding shrinks), and a prerendered /offline page with an explicit status. Pin Last-Event-ID forwarding through the notification stream proxy so a reconnecting EventSource replays the gap. Add an SSR accessibility audit of the sign-in, setup, workspace, offline and approval markup (one h1, a main landmark, labelled controls, named buttons, image alt text) with WCAG contrast checks for the shared palette, and pwa.spec.ts covering installability, the offline shell and a refused offline submit, phone and desktop layouts without horizontal overflow, keyboard skip navigation, axe scans and stream resumption. Document the PWA in the README. Stamp PWA-01 complete-with-external-verification with gate PWA-01-E1 on REL-01 and update the backlog index and frontier.
Add docs/release-acceptance.md, which maps each REL-01 acceptance criterion to the Compose job steps, PostgreSQL jobs, browser scenarios and integration suites that prove it, describes how to cut a release candidate, and lists the manual checks a release manager runs on it. Add infra/release-manifest.mjs, which writes the reproducible release document (commit, package versions, schema tip, pinned Node and PostgreSQL bases, built image ids) and a test proving two runs on one tree agree. Link the guide from the README. Move REL-01 to ready-for-agent now that every blocker is implemented, record the evidence map and the remaining external steps on the ticket, and update the backlog index and frontier.
… full test run found Running every layer locally — Playwright in Chromium, the PostgreSQL suites, the S3 suite and the Compose job — surfaced defects the pg-mem and HTTP walkthroughs could not: - The runtime role had no privileges on the tables added since ROUT-01 (notifications, group_notification_settings, conversation_event_mentions, instance_settings, workspace_exports, the purge manifest and receipts) and no UPDATE on the workspace deletion columns, so the worker's pause check, the inbox, mentions, exports and soft deletion all failed under openbot_runtime. The privilege script now grants each of them the minimum it needs. - The append-only and immutability triggers refuse every DELETE, so the scheduled purge could not run outside pg-mem. Migration 0061_purge_role_exemptions re-emits every guard attached to a DELETE trigger, generated from the ledger and applied after the late guard blocks, with a first clause that lets current_user = 'openbot_purge' through; the audit ledger's guard is excluded. The privilege script provisions that LOGIN role with SELECT and DELETE on exactly the handler tables (pinned against PURGE_HANDLERS) plus the rows the purge writes, the worker connects it via OPENBOT_PURGE_DATABASE_PASSWORD and reports task_worker_retention_unconfigured without it, and purge-runtime.test.ts proves the owner and runtime role stay refused while the purge role removes a deleted workspace and keeps its neighbour. Compose, .env.example, CI and the deployment and upgrade guides carry the new setting. - The notifications page listened for unnamed SSE messages while the stream emits named events, so live updates never arrived in a browser; it now subscribes to each workspace event type. - The routine form only revealed the cron fields after a server round trip; the kind select is now bound so they appear immediately. The routine e2e fixture lacked the member, routing and notification services the group page loads. - The deletion e2e fixture assumed the seven-day grace the lifecycle no longer hard-codes; it now sets the instance retention it expects. - The backup Compose service built the API image a third time in parallel, which races on Docker Desktop; it reuses the built image instead. - pwa.spec.ts waits for the controlling worker, exercises the setup form offline on an unclaimed instance and visits real administration routes. - Ledger-tip assertions in two PostgreSQL suites and the release manifest follow MIGRATION_VERSIONS; the legacy 0022 cancellation test adds the deleted_at column the current services require ahead of its migration. Add playwright.local.config.ts for running the browser suite with Playwright's own Chromium, apps/api/scripts/run-ci-job.mjs for running one Verify job's steps locally, a postgres-purge CI job for the new PostgreSQL suite, and a guide section on running every CI layer on a developer machine. Record the run and its findings on the REL-01 ticket, the DATA-05 ticket and the frontier.
The remote branch carried four commits from a parallel session: a one-time routine UI with bot denial (ROUT-01), an OPENBOT_TELEMETRY switch with a no-op recorder, and Compose health contracts (worker healthcheck, web waiting for a healthy API). This tree already implements ROUT-01 through PWA-01 and has been verified at every layer — browser, PostgreSQL, S3 and the Compose job — so the merge keeps that implementation where both sides built the same thing: - Routine API routes, service, bot-action policy and the web routine pages stay as implemented here; the remote's duplicate routes, pages, per-routine detail page and their tests are dropped because the cron routines, purge handlers and browser scenarios build on the retained versions. - The worker healthcheck and the web service's service_healthy dependency on the API are kept, and both Compose contract tests assert them. - The telemetry switch is not carried: this tree ships no telemetry code at all and idle-outbound.test.ts proves an idle API and worker make no outbound request, which is the stronger promise the README documents. The remote's deploy-baseline contract test is kept without its telemetry case and with the backup tool in the service list; the README gains the exact persistence and private-network sentences it checks. - Ticket, index and frontier files keep this tree's later state.
The root lint runs prettier --check; the files added since ROUT-01 were written without it. Format them and read the purge table list in the grant script by its quoted names so the formatter's quoting cannot break the test.
All 21 jobs passed on 378af9c. List the gate parts that run satisfies (the browser scenarios in CI Chromium, the native PostgreSQL purge, the Compose startup, upgrade, schema-ahead and backup-and-restore steps, pwa.spec.ts) and the parts still open: restricted-role PostgreSQL suites for routines, notifications, exports and deletion, the S3 object purge and scheduled-purge observation, host-level idle-network observation, and the manual PWA and release checks.
… Compose evidence Add PostgreSQL suites that run routines, notifications with mentions, exports, soft deletion with restore and the scheduled purge under the deployed openbot_runtime and openbot_purge roles, sharing a fixture that provisions both roles through the privilege script and seeds a workspace through the production services. The purge suite now also proves a mid-run store failure resumes, the full-text index forgets the target, and the neighbour keeps its rows and objects; an S3 suite proves the object purge against the S3-compatible fixture. Those runs found three defects on real PostgreSQL and fixed them: finalize deleted invitations before the memberships that reference them; Bot versions and Bots reference each other through a deferred constraint, so the Bot handler now deletes its tables in one transaction (handlers may be atomic); and the generated DELETE-guard exemptions missed CONSTRAINT ... AFTER triggers such as the delivery-prefix guard. The export update grant gains sha256. The Compose job observes that an idle stack opens no outbound connection (infra/verify-idle-network.mjs over /proc/net/tcp), that the owner's session survives a restore, and that a soft-deleted workspace is purged by the worker through the deployed stack with only its receipt left; pwa.spec.ts asserts the browser's own installability verdict through DevTools. A postgres-features CI job runs the new suites and the object-storage job runs the S3 purge test. Record the findings on the DATA-05 ticket. The isolated-schema PostgreSQL suites now migrate the public schema before creating their own: the SECURITY DEFINER guard functions compile their %ROWTYPE declarations against public, so on an empty database those suites only passed when another suite had happened to migrate public first.
All 22 jobs passed, including postgres-features, the extended postgres-purge suite, the S3 object purge, the browser installability verdict and the Compose idle-network and scheduled-purge observations. Mark ROUT-01 through PWA-01 complete, record the run on their tickets and on REL-01, and update the backlog index and frontier: only REL-01's four manual checks remain.
Setup, invitation acceptance and the API validator now accept passwords of eight characters or more; the upper bound of 1024 bytes is unchanged. The setup and join forms, their error messages, the page test and the browser fixture follow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
OpenBot is a self-hosted Bot collaboration system supporting configurable OpenAI Chat Completions, OpenAI Responses and Anthropic Messages-compatible endpoints.
This draft implements the 67-ticket, 401-criterion backlog. 29 tickets are now fully implemented, independently reviewed and verified. All original acceptance texts are preserved. Cloud computers are excluded.
The latest feature cancels queued and running Task trees with current authorization, aborts active or silent provider requests, preserves interrupted output across stream reclamation and reload, and rejects late answers. Stable command receipts recover lost responses. The subsequent narrow CI correction handles migration 0023 on databases containing queued Tasks and preserves the typed timeout after a blocked stream write. Both passed independent Spec and Standards reviews.
Current publication
ad96195402ea48e0ceabf795d945db1d46cd2289matches accepted localc7dcdcb6b3848a89407c76664869f8290d0fe9c5, tree28161d0dd57032184fec224c3a838ddf216c87e6, verified by fetch and pinned diff. The actual PR checkout69164ce0b50efbafe5e12862cb951b6476c1a960has that exact tree.Verify 33968122031 completed 2026-09-05 13:10:21–13:16:39 UTC, all 16 jobs successful:
COL-07-E1 is closed. The repository checkpoint is updated locally and will accompany the next accepted publication. Discovery skips are excluded; no local PostgreSQL or Docker execution is claimed.
The preceding failed Verify 33967009969 remains recorded: 13/16 jobs passed, with a populated-upgrade deferred-trigger error and two Task/stream deadline error boundaries. The narrow correction evidence records the actual failure, a witnessed regression and focused checks. The subsequent successful run above verifies the corrected source.
Previously completed features include authentication/OIDC, workspaces and roles, personal/shared model connections and capabilities, Bot identity/ACL/avatar/versioning/copy/lifecycle, groups and history grants, durable conversations and separate-worker Tasks, ordered live replies and reconnect, deterministic Bot routing, immutable manual retry history, scoped group memory, private attachments with tracked purge, API tokens and the public Bot API.
COL-10 automatic retries/fallbacks, MEM-02 Bot-private memory and KNW-01 cited file knowledge continue in isolated worktrees; reviewed precursor slices do not close those full tickets. 38 tickets remain: 3 in progress and 35 awaiting their actual dependencies. Main remains
ecc586a8d3b528728af2308e247c4c3c4fb75ffa; PR1 remains draft while the complete backlog and release gates are implemented.