Repository navigation
v1.34.0-rc.10
Pre-releasev1.34.0-rc.9 was tagged but never published: its release build failed (the web apps did not declare lucide-react, which the shared design kit imports) and its public snapshot did not compile (release.sh committed the unpatched no_obs stubs). rc.10 carries the same changes plus those two fixes.
Pre-release on the edge channel; everything since rc.8 (2026-09-21): Agent Access (off by default), the
post-Agent-Access backlog and its two live-verification rounds, the finish round (the shared design kit,
maker-over-reseller prices and Claude Sonnet 5.5, code-vs-comment lines, commit ownership, org session
gauges, the org daily spend summary), opt-in retroactive re-pricing, sandboxed-terminal containment, a
node dashboard performance pass and chart time granularity, with the review folds of each round.
Migrations: agent 127-147 (node-local or additive; they run on observer start), server 160-189 /
PostgreSQL 0026-0055. On the org server run observer-org upgrade preflight and then
observer-org migrate before starting the new image (PostgreSQL 0032 needs btree_gist; on Azure
Flexible Server see the btree_gist entry below). Node binaries need updating too. On a node that was
enrolled before this release, run observer org resync once (dry run by default; --confirm to queue)
so rows that changed or were corrected on the node before the re-send lane existed reach the org.
-
chore(config): the flat
[org_client.share]obs_summary/obs_traces/obs_content/obs_eval_summaryaliases are removed from the schema - the same leak as the code-graph blocks: the struct fields still existed, so every dashboard save /observer config setwrote them back and every observer process kept printing their deprecation lines. A config still carrying them keeps loading (the keys are ignored;[org_client.share.obs]is the only spelling read);observer start/observer config migraterewrite them on disk (config-migrate step 5,config_version = 5): leftovers beside the nested keys are stripped with the nested values kept, a flat key with no nested counterpart is moved onto it, and a never-migrated file still has its values carried by step 2. What ships to an org is unchanged. A new invariant pins that no key the migrate registry retires can come back as a config field. -
chore(config,codeintel): the legacy
[compression.code_graph]/[intelligence.code_graph]config blocks are removed from the schema. They outlived their one-release deprecation window because the config structs still existed, so every dashboard save /observer config setwrote them back and the deprecation warnings never stopped. A config still carrying them keeps loading (the keys are ignored);observer start/observer config migratenow strip them (config-migrate step 4; a never-migrated file still has its values carried onto[codeintel]first). The dead Settings -> Intelligence "Code graph" toggle is gone -codeintel.enabledis the switch. -
feat(agent-access): Agent Access - SuperBased-minted agent identity and a governed MCP gateway (optional, OFF by default:
[agent_access].enabledon the org server,[mcp_relay].enabledon the node; both inert and byte-identical when off). A new companion binaryobserver-mcpgw(roles sts / pdp / xds / front / connect / egress) runs a Go MCP policy front in front of a stock, digest-pinned agentgateway v1.5.0 (ADR-0007, data plane A2). Every governed MCP call is authorised by one in-process policy decision point and recorded before it acts in a per-org hash-chained audit (async by default, fail-closed only when neither a leased sequence block nor the spool is writable). Tokens: RFC 8693 exchange for node relays,client_credentials(private_key_jwt incl.jwks_uri, mTLS, client secret,sbo_mcp_API keys), an OAuth 2.1 authorization server with DCR and CIMD for direct MCP clients, and end-user OBO. Bearer by default, DPoP / mTLS opt-in per virtual server. Seedocs/agent-access.md. -
feat(agent-access): MCP server registry, virtual servers, grants (incl. team and project subjects, fail-closed without trusted context), single-author policy publish with optional four-eyes, snapshot pinning with drift alerts, per-user OAuth connections (sealed per record; My Connections in the org dashboard; the connect callback lands on the dashboard origin), TOCTOU-safe parked approvals bound to the request digest and the live connection pin, MCP server / tool token budgets (
budgets.scopegainsmcp_server/mcp_tool), shadow-MCP discovery from node inventories, and an MCP-calls panel in the node session detail and the org session drawer. Org migrations 163-173 (PostgreSQL 0029-0039), node migrations 131-134. -
feat(agent-access):
observer-org agent-access- the full admin CLI (server,vserver,grant,policy,agent,credential,key,approval,connection,audit,reset-bootstrap,purge-subject <id>,reapply). Routed verbs run the dashboard's own handler in-process and write the same audit row ascli:<os-user>;purge-subjectis the DSAR / deprovision cascade (credentials, API keys, OAuth AS grants, crypto-erased vault connections and IdP artifacts, task bindings, dashboard sessions, member generation; audit tables never touched). -
feat(agent-access):
observer-org agent-access reapply --since <T> --from <source>re-applies, forward only, the security actions a point-in-time restore silently undoes (purges, credential / API-key / OAuth-client revokes, connection and IdP-artifact erasures, agent / server retirements and quarantines, private-network locks, key rotations and retirements, the policy-generation floor, member session revokes) from the pre-restore database (read-only), the split data store, or a saved/api/org/auditpage - never the MCP WORM export. Each step probes, applies only if missing and re-probes through the seam the original used;--dry-runwrites nothing; a real run (--confirm) writes oneagent_access.reapplyaudit row and then makes every restored refreshable connection due for refresh so reused tokens are re-detected. Run it before the restored server takes traffic. -
feat(agent-access): node
observer mcp {status|relay|wrap|unwrap|connect|doctor}(the olderobserver mcp-relayspelling stays); the node dashboard Security page gains an "MCP access" section andGET /api/mcp-access/status; the VS Code extension gains an "MCP access" status item. -
feat(agent-access):
observer-org doctor agent-access(probes AA1-AA10, each naming its failure mode), Agent Access rows inobserver-org upgrade preflight(schema range, normalized listener conflicts, key-ring health, the observer-mcpgw same-tag lockstep and agentgateway pin), anagent-access.jsonsupport-bundle section, and an Agent Access alert rule set (pdp_down, pdp_degraded, audit_degraded, xds_nack, sts_down, replay_store_down, control_store_down, stale_replica, jwks_rotation_stall, mcp_budget_breach, vault_refresh_failures; mailed under[dashboard].obs_alert_email).[agent_access].companion_health_urlslists several companions for split and multi-replica deployments:pdp_downthen pages only when every companion is down andpdp_degradedwarns per down companion. -
feat(agent-access): backpressure on the MCP front: PDP decision deadline
pdp_decision_timeout(default 1 s; ~250 ms stays the latency target), per-call upstream deadlinehop_call_timeout(120 s; first byte for SSE), a per-upstream circuit breaker (hop_breaker_failures5,hop_breaker_cooldown10 s) and an overload shed (front_max_in_flight1024). All answer a retryable 503 +Retry-After; nothing retries a call. -
feat(agent-access): Azure Key Vault signing keys rotate through the product:
observer-org agent-access key rotateadds (or, with--akv-key-version, adopts) a Key Vault key version to the ring through the same ACK-gated activation,--emergencyincluded; an identity that cannot create versions gets a 409 that prints the exactaz keyvault key create+key rotate --akv-key-versionstep. The front's own key cache is bounded bymin(invalidation_max_staleness, jwks_cache_seconds), sokey retiretakes effect at every running front without a restart (a key-set outage answers 503 +Retry-After, never 401). -
feat(deploy,charts,release,supply-chain): Agent Access in every deployment shape, off by default everywhere, with one topology:
observer-mcpgwand the agentgateway sidecar share the org's network namespace and sit behind the existing TLS terminator on ONE origin (the STS paths to :8850,/mcp/*and its protected-resource metadata to :8851, everything else to :8443; no new DNS name, certificate or public port). Org compose (production + dev) gains adocker-compose.agent-access.yamloverride, an inert[agent_access]block, a Caddyfile with the path routes,keygen.sh agent-access-envand preflight checks (OBSERVER_AGENT_ACCESS_COMPANION=externalkeeps the separate-host companion supported); Helm chart 0.3.0 gainsagentAccess.*(companion in the worker pod by default);observer-org deploy plan --set agent_access=onrenders the whole switch (config, .env, the override, tfvars, RUNBOOK checklist and route table); every Azure and AWS OpenTofu root gainsagent_access(session key minted in Key Vault / Secrets Manager, Caddy / HAProxy / Application Gateway / ALB path routes, first-boot cosign verification, and refusal of a bundle that disagrees). At zero virtual servers the companion writes an idle hop config, so the sidecar stays up and the companion reports ready. -
feat(supply-chain): doc3 §18 gate 7 as code -
.github/workflows/agent-access-images.yml(runs on everyv*tag, separately from the npm / PyPI / Marketplace release) buildsobserver-mcpgwfrom an archive of the tag, emits SPDX + CycloneDX SBOMs, gates on a grype CVE scan against the ruled patch SLA, pushes by digest, cosign-signs keylessly with SBOM attestations and SLSA provenance, and mirrors the agentgateway image only after verifying upstream's signature and provenance, then counter-signs it.scripts/agent-access-supply-chain-check.shis the one policy owner (pins / identity / upstream / verify / gate); dated, ledgered exceptions live indeploy/observer-mcpgw/cve-exceptions.json;roll-a2.shverifies before every pull. The air-gap kit carries both images once that run has published them. Publishing needs registry credentials; without them the jobs build, scan and skip publish. -
feat(org-assistant): the admin assistant reaches every admin route: its closed tool table grows 58 -> 212 rows (every admin route is mirrored by a row or carries a reasoned exclusion, pinned by
TestEveryAdminRouteIsReachableOrExcluded), then 212 -> 247 with the Agent Access admin routes (4 read views, 31 route rows - 30 writes plus a simulate read - under the domainsagent_accessandmcp; minted secrets go once to the approver, never into the transcript; the approve / reject decision routes stay human-only).admin:agent_principals,admin:agent_keys,write:mcp_registryandwrite:mcp_policybecome privileged keys: granting or widening them (dashboard or assistant) needs the super admin. -
fix(agent-access): the PDP no longer serves its last-known-good policy forever (
invalidation_max_stalenessis enforced at decision time;/healthzgoes not-ready past it); an agentgateway dying mid-response is answered with a retryable error and auditedhop_unavailableinstead ofok; the front's hop client pools connections; the front refetches the key ring within 1 s of an unknown kid (was 30 s: a 401 storm after every rotation); a node relay no longer reports a refused policy version as running. -
fix(agent-access): honest readiness and retryable outages: a NEW policy publication that fails to compile is refused and the replica keeps last-known-good (then fails closed at
invalidation_max_staleness); the renderedhop.yamlis checked with the pinned agentgateway's--validate-onlybefore it replaces the live file;/healthzgainsaudit_store_erroranddpop_replay,audit_degradedpages on a data-store outage and now clears on recovery (it was sticky until restart), and a newcontrol_store_downalert rule; an ineffective node relay point reportsaccepted_inert, nevereffective; the relay keeps a still-valid cached token while the STS is down and fails closed only within 5 s of expiry; transient store outages at the token endpoint answer 503temporarily_unavailable+Retry-After: 2; arefresh_tokenrotation is undone when the mint fails, so a retry is no longer mistaken for reuse. -
fix(agent-access): security fixes from the session-3 adversarial reviews (ledger
docs/security.mdAA-13..AA-23, AA-GEN-1): an ambient HTTP proxy no longer bypasses the egress SSRF guard (explicit[agent_access].egress_proxy_urlinstead); approval redemption is fenced on the live connection; duplicate JSON members are refused before any decoding; approval previews requireread:content; SCIM and team-admin roster changes commit atomically with the member-generation fence; every revocation strictly advances the member floor; a zero-estimate MCP call's quota reservation persists the unit it was checked against; discovery retention prunes the control store on split deployments. -
fix(agent-access):
deploy/observer-mcpgw/docker-compose.a2.yamlsetsstop_grace_period: 45s(Docker's 10 s default cut the companion's drain short); theistio.io/istiodependency moves past GO-2026-5363 / GO-2026-5289 (govulncheck: 0 reachable in all three binaries). -
fix(deploy,observer-org): PostgreSQL migration 0032 creates
btree_gist, which Azure Database for PostgreSQL Flexible Server refuses unless it is inazure.extensions: the Azure OpenTofu module now allow-listsBTREE_GIST(a drift test fails when the lineage creates an extension the module does not allow), andobserver-org upgrade preflightgains a<plane> extensionsrow per PostgreSQL store that refuses before migrate when a pending migration needs an extension the server will not allow, printing the exact fix. A server not managed by the module (for example an existing demo estate) needs the printedaz postgres flexible-server parameter setstep before the roll that carries 0032. -
fix(support-bundle): doctor.txt ran with the support-bundle command's own arguments (cobra reads os.Args when args are nil) and never held the doctor's output; config.redacted.toml no longer carries URL userinfo (a proxy password in
[agent_access].egress_proxy_url/serving_replicas). -
feat(sessions): Tok/s has one owner. The Messages table's throughput used to divide output tokens by the gap to the next row (idle time read as generation time); it now divides by a measured per-call duration - the proxy's request time, the tool's own recorded per-call time (devin, hermes, poolside, muse, legacy copilot, cowork) or spans reconstructed from the Claude Code / Codex transcript - and shows "not measured" otherwise; the gap is shown only as "Elapsed". The node Messages tab, the cockpit and the org session drawer render the same value (
token_usage.gen_ms/gen_basisship on the org wire as metadata). Agent migration 136, server 174 / pg 0040. Seedocs/message-throughput.md. -
feat(pricing): frontier model price refresh (2026-09-23: Anthropic, OpenAI, xAI, Cognition) folded onto the seed with presence semantics (a dimension the snapshot omits keeps the seed value; a stated one wins, a quoted zero included); a feed replay / downgrade floor; cache reads a vendor does not price surface as unpriced instead of $0.
org_model_prices.long_context_thresholdbecomes nullable (server 175 / pg 0041): NULL keeps the node's seed long-context tier, a quoted 0 means negotiated flat;orgcontract.PricingPolicyRow.LongContextThresholdis*int64on the signed rail (compatible both ways). -
feat(model-pricing): tokcron, an approval-gated refresh job for the Tokenomics data behind the public pricing feed: it re-fetches vendor endpoints, gates hand-captured prices against vendor pages it fetched itself, rehearses on a local database and writes a proposal only when the feed would change; only the operator's interactive approve step (re-proved on a throwaway clone of production) reaches production. See
model-pricing/deploy/tokcron/README.md. -
feat(org): bulk developer import -
POST /api/org/members/import(dry run, up to 200 rows, preflighted refusals before any mint, itemized per-row status and honest deliverynotifier_invoked/no_notifier_configured, audited) and an Import developers dialog on the Provisioning page (paste or CSV). -
feat(guard): control coverage per tool - one row per tool joining the tool-call enforcement channel, the prompt-submit posture, budget admission and route proof, on
observer adapters,observer doctor <tool>,GET /api/org/guard/coverageand the org Security page. -
fix(org): every session-scoped org read and every org correlation that joined on a bare session id is now bound to the session's owner (sessions are keyed by id AND user; a same-id session pushed by another developer can no longer be read through, merged into, or counted against a colleague's), including Live, the monthly report, LOC aggregates, the route matrix and coding-job evidence (an ambiguous owner is refused rather than guessed); task prose, the raw action target and the raw
project_rootare served only to callers holdingread:content(ledger ORG-SCOPE-1 / ORG-CONTENT-1 / ORG-SCOPE-3). -
fix(org): project display names never show a hash-seeded placeholder when a repository name is known (one resolver for the Projects list, project detail, sessions, budgets and team views); the org Tools page gains a per-tool version histogram (
GET /api/org/tools/versions). -
fix(alignment): the Projects-page local LLM judge (tier J) refuses to send org-owned or unknown-authority evidence to a non-loopback endpoint unless it is org-pinned; loopback detection is an exact host match (ledger JUDGE-1).
-
fix(cursor): Cursor IDE sessions no longer lose their token rows - the hook writes tokens first under their own deadline, Cursor's own hooks log is replayed as a backstop (deduplicated against the live hook), root-less events resolve to the session's real project root, and stale hook entries left by a lost build are healed on registration (
observer doctorcheckcursor.hooks;observer backfill --cursor-hook-usagerecovers history). -
fix(deploy): the Azure env-sync re-applies a secret rotated in Key Vault to an already-rendered
.envvalue and tracks what it applied per key (pending / committed / operator_override), so a crash on either side of the write is recoverable and an operator's own value is never overwritten (D-DEMO-16). -
fix(configschema): the committed
[mcp_relay]annotation rows that the embedded config schema was generated from (make verify-config-schemais green again). -
docs(agent-access): operator reference
docs/agent-access.md(incl. a per-profile enable checklist); runbooks for key rotation, restart while routed, audit degraded, vault refresh and CVE patching;docs/agent-access-production-gates.md(doc3 §18: gates 1-3 and 5 pass locally; the gate-4 reapply tool is built but the drill has not run; gate 7 is built as code with enablement pending registry credentials; live client interop not run); the vendor pen-test scopedocs/agent-access-pentest-scope.md. Not yet done: push and deploy, the estate soak, the external penetration test, the six-agent security sweep, the live Azure Key Vault and client-interop checks. -
feat(projects): a new Skills tab on the node Projects detail panel (and
observer project <id|root> --skills) shows every skill a project can load (.claude/skills/<name>/SKILL.mdand~/.claude/skills), how each changed across the project's commits (versions identified by git blob id; added/modified/deleted, reintroduced, exact-content moves), and per session three separate facts: the version the Claude Code hook OBSERVED on disk at session start (SessionStart incl. resume/compact), the version committed at the commit the git REFLOG says HEAD was on, and the version each Skill-tool invocation used (PostToolUse, joined by tool_use_id). Sessions before capture read "not captured", never a guessed version; "uncommitted"/"untracked"/"ignored" come only from the status porcelain. Capture: hook snapshots (fail-open, 250 ms budget) + a read-only git step riding the commit scanner tick (reflog,ls-tree, status) through the onegitviewenvelope, withGIT_NO_LAZY_FETCH=1added for this step only (a partial clone never fetches). Reflog entries sharing one second are ordered by the reflog itself, and a session whose chosen second holds several commits reads "HEAD moved several times in one second" rather than a guess; same-second commits are ordered by ancestry. Agent migration 135 adds seven NODE-LOCAL tables (privacy sentinel + seeded test);[projects].skill_history(default on) andskill_history_skew_seconds(default 120). Existing endpoints are byte-identical. Seedocs/projects-page.md"Skills: versions across commits and sessions". -
fix(teams): the org session drawer's message rows are derived by the SAME pure code as the node's Messages tab (new
internal/sessionmsg): orphaned actions, proxy/JSONL twins, codex multi-call turns (new wire columntoken_usage.turn_id, server migration 160 / pg 0026), user-prompt keying and Copilot shadow rows now fold identically on both sides; web2 labels a body that exists but joins no row "captured, not aligned" instead of "not shared" and joins tool bodies by id. -
perf(projects): one union activity query, one windowed LOC loader and agent migration 130's three covering indexes replace four correlated EXISTS probes and a whole-ledger LOC scan per Projects read; every project window is half-open
[since, until). -
fix(projects): the Projects page's spend figures (detail panel, the
/projectslist, and everyusdROI proxy) now go through the process cost engine's own per-turn dedup+pricing pipeline instead of a second, drifted implementation - closes several undercounting bugs (session-cumulative adapters like droid/goose/crush double-counted against their own proxy rows; a proxy turn's project was silently dropped wheneverapi_turns.project_idwas NULL, which is every grounded install; a codex-shaped turn's reasoning-token split could double-bill). The commit count shown on the detail panel, the/projectslist and the ROI proxies is now the same reachable-only predicate everywhere. -
fix: the Projects-page Commits/Prompts/Spend tabs now surface a "row caps hit" notice (matching the existing Overview banner) whenever a request-time linkage cap actually truncated their data, and flag a prompt's committed/uncommitted status as uncertain when it was computed over a capped input; the underlying prompt-linkage query and the task-report rollup are both faster (a new covering index and batched, no-longer-N+1 task queries).
-
fix(predict): codex rate-limit snapshots were silently dropped when a client reported
plan_type: nullwith a populated window; codex's 5h/weekly window label is now derived from the window's own duration instead of itsprimary/secondaryposition (a single-window plan was rendering its weekly cap under the "5-hour" label). The next-message predictor's limit gauge gained an honest "not visible" state (CLI, dashboard,/api/session/<id>/predict) for tools where no local usage-limit signal can exist (cursor, grokbot), replacing the misleading "route through the proxy" hint. Runobserver backfill --codex-rescanif your codex rate-limit history has a gap. -
fix(tools): the Connected Tools page now flags compiled-in default adapters that are missing from a hand-written
enabled_adapterslist (a warn banner + a "not enabled (new default)" pill, one owner: theadopt-defaultsdiff), andobserver config adopt-defaults --writestates honestly that the daemon must be restarted before the new adapters capture anything. -
Node dashboard: a new Projects page detail panel (
web/src/components/ProjectDetailPanel.tsx,
web/src/components/projectdetail/) with six tabs — Overview, Spend, Commits, Prompts, Tasks,
Guidance — answering "is the money I put into API tokens turning into shipped work?" per project.
The list view (web/src/pages/Projects.tsx) grows additive spend/AI-lines/commit/capture columns;
an empty corpus keeps a byte-identical legacy/api/projectspayload. Seedocs/projects-page.md. -
Commit capture: a new read-only, HEAD-only
git logscanner (internal/commitscan,internal/commitlog,
daemon-lifetime, never a git hook install,[projects].commit_scandefault on, 120s ticker) populates
three new node-local tables (project_commits,project_commit_files,project_commit_scan, migration
127) with reachability revalidation every tick so a rebased/reset commit is flagged, never deleted.
observer backfill --commitsruns a full-history pass;observer doctorgains acommit-captureline. -
Prompt-to-commit attribution + ROI: a pure
internal/projectroipackage links each AI edit to its
owning prompt, applies a per-file supersede rule, then matches against commits within a configurable
link window ([projects].commit_link_window_days, default 14 days) to produce acommitted/
partial/uncommitted/superseded/no_editsstatus per prompt. Eight ROI proxies (spend per
AI line reached, AI-files-reached share, spend with no linked commit, spend per commit/per completed
task, prompts/turns per commit, cache-read share) each ship their formula and an honesty caveat;
nothing is called "dead" or "line survival" — file-level reach is stated as exactly that. -
Projects page spend is priced at READ time through the process cost engine (recorded cost wins when
0; otherwise the turn's full token bundle is priced at its own timestamp), de-duplicated per turn
across the proxy and transcript captures with the cost engine's own identity rule, and reports
spend.unpriced_turns(turns with no recorded cost and no pricing entry) on the API, the Overview
tile, the/projectslist (spend_unpriced_turns_30d) and the CLI - a corpus that stores $0 in its
cost columns no longer renders $0.00 (found on this repo's own corpus during the 2026-09-22 review). -
observer project <id|root> [--days N] [--json]prints the same per-project summary the dashboard's
detail panel shows, through the one shared composition (dashboard.ComposeProjectDetail). -
Commit capture reports a fourth state,
error(the last scan failed and none has succeeded since),
instead of hiding a failing scanner behindok; full-history scans are paged (500 commits per
bounded git call, 60 s each) soobserver backfill --commitscompletes on a large repository; a
project rooted in a subdirectory of a repository is scanned with its subtree as the pathspec (file
paths re-based onto the project root) instead of being credited with the whole repository's history. -
Alignment grading (delivered vs. missed): a three-tier design — always-on local heuristics (tier L),
an opt-in local/configured LLM judge (tier J), and Cloud Intelligence grading under the existing
extended_evidence_deep_reviewpurpose (tier C,observer cloud grade-commit). Tier C ships its node
contract and request path in this release; the hosted executor is honestlynot_available: hosted kind not deployeduntil it exists, never a fabricated grade. -
Guard, proxy lane: goose's built-in
developer__shelltool is now in the response-side tool
table (responseToolShape), so a shell command goose intends to run is evaluated and flagged
like Bash/run_command; before, goose shell calls were invisible to the proxy's response scan.
Grounded on the demo estate 2026-09-21 (session 7). Response-side scanning stays flag-only. -
Org dashboard, Guard tab: the bundle editor's rows are called RULES ("+ Add rule", "Rules (n)",
"Remove rule"); before, "+ Add override" shared a card with "Developer may override" (the
developer exception), one word with two meanings, which made a multi-rule bundle read as a
one-rule form. The[[override]]TOML key is unchanged. -
Org fleet findings: the evaluator's GRANTED set now includes the authority of the fleet grant-replacement
generation a member acked under the enterprise posture (through the posture-owned
AckedAuthorityByMemberseam), not only the member's enrolment token. Before, every node that accepted
the org's own fleet document was raised asauthority_divergence("accepted authority that was never
granted") the moment it reported - D-DEMO-14, found on the demo estate on the first policy-acks after
rc.8. A member that accepted tokens beyond its acked document is still flagged; an orphaned ack row
never resurrects a deprovisioned member; on a split control store without the posture tables the fold
is empty by construction and every other error is surfaced. -
Org CLI:
observer-org policy publish --team <id>(repeatable) publishes a TEAM-scoped guard bundle
through the same path the dashboard's Guard tab uses (composed strictest-wins on the org-wide floor
for members of those teams); without--teamthe command is unchanged (org-wide). The wave contract
named the CLI and only the API/dashboard had it. -
Node, org governance: the effective-policy-state reporter is now constructed on every org-client node
and stays dormant until its channel is enabled, so an org raise of thepolicy_stateshare (enterprise
default body,extract.policy_stateauthority) reaches a managed node whose local
[org_client.share].policy_statewas left off. Before, that raise had no reporter to act on: the node
never posted a policy-ack and the org's fleet findings read every governed developer as
governance_lapsed("never reported a governance state") - D-DEMO-13, found on the demo estate the
moment the rc.8 sweeper started. Individual nodes are unchanged (the org cannot raise the share there). -
feat(ui): dashboards UI pass 1 (web, web2, cloud portal): one shared CSS motion layer (route enter, stagger, count-up, reduced-motion safe, transform / opacity only, no animation library); one query cache per app (concurrent requests deduplicated, stale-while-revalidate across mounts, visible staleness instead of old data shown as current); terminals follow the app theme by default and can be pinned light or dark in the terminal header; the shared Tailwind preset's opacity fix revives ~880 classes that rendered nothing, and
fg-3text meets WCAG AA; web2 and the portal are route-split (first-paint JS: web -18%, web2 -79%, portal -55%); quiet sessions poll every 60 s instead of 8 s. Reportdocs/audits/dashboards-ui-review-2026-09-27.md. -
feat(ui): UI pass 2: the Cost chart overlays its series; the "Actions over time" legend no longer overlaps the top y-axis label; a query-key bug that requested
/nullis fixed; one shared slide-over with a focus trap; the open drawer and its tab live in the URL; filters are route-aware; the cloud portal's buttons, cards and switches come from the shared primitives. -
feat(ui): the shared design kit across all three apps (plan
docs/plans/dashboard-visual-upgrade-tracker-2026-09-28.md, WS1-WS10): real vendor logos for every tool key with capture-surface pips and a monogram for an unknown tool (attributions inshared/lib/THIRD_PARTY_ICONS.md); model-family, host and IdP marks and one shared model-id renderer; an SVG brand mark, branded loader and boot screens; one icon system; one tone vocabulary so the same status reads the same colour and pill everywhere; illustrated empty states, loading and error states, and a permission-denied state (a 403 is a denial, not an error); live signals (live dot, meters, progress rings) and number tweens; one Modal / Toggle / ConfirmButton / CopyOnClick / Tooltip; table hover and zebra rows; chart legends; branded sign-in shells for the org dashboard and the portal; radial gauges in the session detail. -
feat(ui): finish-round UI pass 3: a density toggle (comfortable / compact) in all three apps; the node's hand-rolled tables move onto one DataTable (sorting, numeric alignment, a loading state), now a single shared component with web2's row expansion; filters in the URL (node: window, range, tool, project, search; org:
?days=on every route); sidebar collapse on the node and org dashboards; the web2 Spend figure counts up; the Security pages and org Settings fit a 390 px screen; a 403 on any chart or panel renders the shared permission-denied state. Behaviour changes: a cache row flagged by the engine is amber (warn) everywhere; destructive deletes need a two-step confirm (org: team, budget, dated rate, alert rule, project-identity rule, deployment connector, intelligence provider, virtual-key revoke, announcement retract, dataset item; node: Remote "Revoke all", arena candidate discard, "Run retention now", the terminal's "Stop & close"). Source maps are builthiddenand never shipped in the embedded bundles. -
feat(ui): the custom time range is a picker, not typed datetime fields (node and org): one-click presets (Today, Yesterday, This week, Last week, This month, Last month), a Monday-first month calendar (start day, then end day; future days disabled) and hour / minute selects; the end defaults to Now. The org dashboard's rollups are trailing windows, so its picker chooses a start and runs to now.
-
feat(dashboards): charts bucket by the window - 5 min / hour / day / week in the viewer's time zone, zero-filled, with a per-chart Auto / 5 min / Hour / Day / Week control (only the buckets the window allows, at most 2,000 points; an over-cap request is a
400 granularity, never a silently coarser chart; the choice travels in the URL asgran=). Auto picks 5 min up to 3 hours, hour up to 7 days, day up to 180 days, else week. Node: every time-series endpoint now honours the selected window (analysis trend, cache-savings trend, cost-by-hour, cost-by-day-of-week-hour and cache timeseries used to serve 30 days on 1h / 12h / custom), and the Analysis headline, movers, top sessions and routing suggestions and the Cache overview and events follow it too; the raw proxy-only hour query (which dropped transcript rows) is gone. Org: the window ladder gains 1h / 12h / custom (additivehours/since/until/gran/tzparams; a days-only request keeps the daily response); sub-day spend is read from raw rows within the cap and Auto picks Day above 2 days; charts fed by daily pushed summaries offer Day / Week with a "daily data only" note. Cloud portal: day labels and a daily-data note. Review fold: the zone database is compiled in, so a Windows node buckets in the viewer's zone instead of silently in UTC (a fallback says "UTC buckets (zone unavailable)"); every series on a page agrees across DST changes; malformed timestamps no longer 500 on PostgreSQL; zero-filled org series show their empty state again; window-scoped analytics answers of a day or less are at most 30 s fresh. Plandocs/plans/chart-time-granularity-plan-2026-09-29.md. -
perf(dashboard): node dashboard performance audit on a real 27 GB database, and fixes (
docs/audits/node-dashboard-performance-audit-2026-09-29.md): a stale-while-revalidate response cache for 30 heavy GET endpoints (inside every guard, invalidated by dashboard writes); polls re-arm only after the previous one settles; the Sessions list polls every 30 s and pauses while the drawer is open; memoized table rows and charts, lazy tooltips, cached date formatters, finite illustration animations; the session Messages tab loads only the returned page; agent migration 147 adds covering indexes (sessions activity, excerpt lookup, latest limit snapshot, repeated-command discovery); the process-to-action correlator searches a sorted time window instead of every action. Measured on a copy of that database: drawer tabs 38-240 s -> 1.2-10 s to data-complete, Overview 157 s -> 54 s cold / 17 s warm, Analysis 111 s -> 33 s / 0.6 s, Discovery 60 s -> 12 s / 0.5 s, Cost 76 s -> 16 s / 6 s, Report 22 s -> 0.5 s; blocking time on drawer tabs 2-23 s -> 0.1-0.7 s; the correlator 6.2 s -> 71 ms on 20k x 15k. The org dashboard and the portal inherit the shared client fixes. On the live daemon (cold, first visits after a restart): Overview >240 s -> 93 s, Analysis 116 s -> 61 s, Discovery >240 s -> 27 s, Report 58 s -> 0.4 s, session Messages tab 207 s -> 5.4 s; idle main-thread use 5-35 % -> 1-2 % on every page. -
perf(dashboard): the Sessions list uses its index again - the default sort repeated
started_at, which kept SQLite offidx_sessions_startedand scanned every session before the page limit (/api/sessionsfirst call 4.2 s -> 0.14 s, byte-identical responses, plan pinned by a test); the Overview stale-reads tile asks/api/discover?sections=staleinstead of computing the whole discovery report (5.7 s -> 0.23 s warm; it was the last panel on a cold Overview); chart first mounts take turns instead of mounting about ten charts in one task (Analysis blocking time roughly halved); bar charts with more than 400 bars (a 7-day hourly trend is about 1,200) draw without the entry animation. -
perf: optimization review (
docs/audits/optimization-review-2026-09-27.md): node Overview 40-47 s -> 11-21 s, Analysis 14-16 s -> 9-12 s, Cost 7-8 s -> 4.5-5.5 s, Sessions 8.5-9 s -> 6.8-7.4 s on a real 21.5 GB database copy (agent migration 138 covering index, a dashboard-only raw-row cache in the cost engine, serve-stale-then-refresh for/api/statusand watcher health); org session drawer spend queries ~716 ms -> ~10 ms on a 900k-row PostgreSQL store (server 176 / pg 0042, indexes only); the org rollup cache shares concurrent cold loads and an invalidation beats an in-flight load. -
perf(org): a daily deduplicated spend summary (
spend_daily, server 184 / pg 0050) written at ingest by one writer from the same per-row projection and duplicate-count verdicts as the live spend query; every ingest path, re-send, moved row, tombstone, scrub, purge, eviction and prune refreshes the affected units in the same transaction. Overview, Projects, People, Teams, Tools, Models, Movers, reports and budget totals read it (a window is split into live head, summary middle and live tail; until the boot rebuild has stamped the summary every reader stays on the live tables). Measured on a 462k-token-row fixture: Overview 15.9 s -> 1.2 s (PostgreSQL), Projects 10.2 s -> 0.45 s, budget total 834 ms -> 60 ms. The session drawer, Live, workspaces and the People model ladder stay on the live tables. -
feat(pricing): prices come from the Tokenomics database with their history: the public feed carries a per-row
historyof dated periods, the org importer keeps every period, and the cost engine prices each turn at the period in force at its timestamp (a period the source does not state is an honest miss, never a guess); the compiled seed snapshot is generated from the signed feed and the hand-maintained dated timelines are retired. New or corrected rows include claude-opus-5-5-fast (was billed at half its fast price), mimo-v2.6-flash / -pro, Moonshot's dotted kimi-k2.6 / k2.7-code ids, gemini-3.5-flash-lite (was billed as 3.5 Flash), gemini-3.1-flash-lite (was billed as 3.1 Pro) and the composer-2.5-fast cache read; Copilot CLI Auto sessions record the model Auto chose instead ofauto. -
fix(pricing): the model maker's price wins over a reseller's. The feed export ranked offerings without preferring the maker, so reseller cards (Venice, Azure AI Foundry, Novita, OpenModel.ai) won for 16 models on the public feed from 2026-09-16 (for example Claude Opus 4.5-4.8 at $6/$30 instead of $5/$25 per million, gpt-5.4 input at $5 instead of $2.50); feed version 5 pins each maker's page, and the export's maker preference plus a guard listing reseller-won ids whose maker publishes a card follow in the next Tokenomics publish (open-weight ids such as gpt-oss-120b stay reseller-priced on purpose). Costs already stored at the reseller rates are not changed automatically: use the new re-price (below). On an org server, feed-owned price rows now mirror the latest applied feed (a first poll that answers 304 still catches up), so a stale imported reseller row can no longer stay in force in the org's price book, the gateway rate card or the enrolled nodes' signed pricing documents.
-
feat(models): Claude Sonnet 5.5 (
claude-sonnet-5-5): a 512-token minimum cacheable prompt in cache tracking and a 1M-token routing context window; the price ($2 in / $10 out / $0.20 cache read / $2.50 5m and $4 1h cache writes per million, no long-context tier) arrives through the pricing feed, not from a hand row in the binary. -
feat(pricing): opt-in retroactive re-pricing of stored costs, node and org (closes
PRICE-REPRICE-1). Capture still stamps the cost; a re-price is an explicit act at the price in force at each row's own timestamp, never today's. Node:observer repriceis a dry run unless--apply(--revert <run>,--list,--since/--until/--model,--json), plus a Settings -> Pricing card; it re-pricesapi_turnsandsummary_callscosts Observer computed itself, never a vendor- or tool-reported cost (integration.TokenTier.ReportsCost, 13 tools), never writes $0 for an unpriced row, keeps the captured figure and a per-run change log (agent migration 145), and re-priced rows reach the org through the re-send queue. Org:/api/org/pricing/reprice*(write:pricing, historyread:budgets, audited before any row changes, fail-closed) and a panel on the Pricing page re-price org-held rows from the org's own dated price book (server 187 / pg 0053) and refresh the spend summary. Review fold: a single dated org row prices only from its date; reverts run newest first (an out-of-order revert is refused and names the later run) and one run holds the claim at a time on the node and the org; the CLI honours an org pricing pin like the dashboard. Nothing re-prices automatically after a new price version, and a re-price never re-runs budget alerts or rewrites gateway reservations. Seedocs/pricing.md"Re-pricing stored costs". -
feat(org,pricing): context windows reach enrolled nodes (an unsigned sibling of the signed pricing policy,
context_windows, covered by the ETag and outside the signed bytes so older verifiers still accept the document), so a node and its org show the same context-gauge ratio. A re-parse can now correct a token row's reliability: a Crush session that grows past one step corrects itself without--crush-rescan. -
fix(org): one duplicate-count rule on every spend surface, node and org. The org drawer header, model split and cost series derive from the same
sessionmsg.Derivepass as the node (it had counted every proxied OpenCode turn twice); duplicate verdicts are stored at ingest and applied by every org list, page and drawer (server 179 / pg 0045; org Overview 30 d on PostgreSQL 71.7 s -> 3.5 s), and on the node by the cost engine, Analysis, reports, budget, live, statusline, predictor, guard token and priced-spend checks, cloud evidence and the task and sub-agent drill-downs (stored node verdicts, agent migration 143; server 182 / pg 0048). OpenCode twins whose output was clamped to 0 because reasoning exceeded the completion now fold (a session had shown 49,554 tokens for ~24.8K on node and org). The org names its push boundary ("as of "); aclaude -psession readssdk · clion the org instead ofother. Remaining: legacy session-less proxy rows always count. -
feat(org): rows a node changes after pushing them reach the org (agent migration 140, server 178 / pg 0044): triggers queue a changed row only when enrolled and a shipped column changed, every row carries a node revision, and the org applies a re-sent row only when its revision is newer (a moved turn is relocated, never doubled). Corrections a node makes by deleting rows (dedup sweeps, merges, identity changes) ship an identity-only tombstone (agent migration 141); ageing deletes (retention) never propagate. Migration 142 fixes the queue triggers, which failed a whole ingest batch on enrolled nodes when a row was already queued.
observer org resync(dry run by default,--confirm,--deletionsdefault on) heals divergence from before the upgrade and backfills session end times. A share-posture change between two sends no longer lands a second org row (server 180 / pg 0046), andobserver-org scrub-content/ the enterprise purge collapse such twins instead of failing on the primary key. -
feat(sessions): sessions get an end time:
sessions.ended_atwas never written by any path (NULL for every session of every tool); a table-driven rule (a session end closes, a later prompt or session start reopens) now sets it inside ingest, so the dashboards stop showing finished sessions as "in progress". Historical sessions pick it up on their next lifecycle event or viaobserver org resync. -
feat(scoring): the session quality score is computed: only the manual
observer scoreCLI ever called the scorer, so almost no session was scored. A daemon auto-scorer ([intelligence.scoring], default on, capped passes, a session counts as ended after 30 min idle) stores all four components (agent migration 137) and a Session quality card shows the breakdown and a stale-score note on the node session detail and the org drawer (server 177 / pg 0043; the org's newer-action count is derived like the node's). The scorer is about 80x faster on the largest session. -
feat(org): context-window and rate-limit gauges on the org session drawer from one shared derivation (context used = newest non-zero cache read over the session's reported prompt budget or the model's context window; over-window and unknown stay unknown, never 100% or 0%). Rate-limit windows reach the org as a new metadata-only wire family
session_limit_snapshots(5 h / 7 d utilization and resets; no headers or counters), gated by[org_client.share].limit_gaugeor full-content sharing (server 183 / pg 0049); agent migration 146 starts an already-enrolled node's cursor at head so its older limit history is not shipped. The node session detail gains the same context gauge. -
fix(codex,cowork): Codex (and Cowork) sessions no longer show a "Rate limit" row between every message. A rate-limit reading is recorded only when the limit really changes (status, plan, window, used percent by half a point or more, or a reset moved by more than 10 minutes), plus a 15-minute heartbeat that keeps the usage gauge fresh - on the author's own history that is about 9,100 readings instead of 53,500. In the session Messages tab, readings fold into the message they follow and a small badge (for example "7d 74%") marks only the turns where usage changed; node and org drawer derive this from the same shared code. Already-captured readings fold at display time; nothing is deleted.
-
feat(org): the Claude Code request class (
x-claude-code-request-class: main, subagent, workflow, compaction, auxiliary; anything else stays empty, never guessed) is recorded per proxied turn (agent migration 144), ships to the org as a content-free enum (server 188 / pg 0054); both session-detail APIs return the per-class split and the org drawer shows it. -
feat(org):
sessions.parent_thread_idships as metadata (server 162 / pg 0028) so the org drawer resolves a Cursor sub-agent session's tool account through its parent, as the node does; the per-session AI tool version reaches the org (server 161 / pg 0027). -
feat(loc,projects): AI code vs comment lines on every lines-of-code surface, node and org, from one derivation (code = added + modified code lines, comments = added comment lines, a share only when either is non-zero): session card, Sessions list, the Cost lines-per-dollar tile (code lines only), Projects list, overview, commits, spend and prompts,
observer loc show,observer project, and the org People, person / project LOC cards, "Code lines over time", developer footprint and session drawer (server 185 / pg 0051; an older agent's rows show no split rather than 0%). Honesty fixes: Projects "AI code lines", by-session and commit lines, the reached-line proxy and prompt edit counts no longer include docs and config files. -
feat(projects): the session that owns each git commit, node and org. A table-driven rule: merge, unreachable, foreign-author (a teammate's commit you pulled) and no-AI-edit commits have no owner, never a guess; otherwise most AI code lines, then most files, then earliest prompt, then session id (comment lines do not count; sub-agent edits fold into the parent). Node: an Owner column on the Projects Commits tab, a Commits card on the session detail,
GET /api/session/{id}/commits. Org: an additive commit-ownership wire family (no author identity, no paths;commit_sha_hashalways, the raw SHA and subject only under full-content sharing; server 186 + 189 / pg 0052 + 0055), audited org session and project commit views, subject and raw SHA only withread:content. The local git author is stored as a hash only (agent migration 146). Seedocs/projects-page.md"Commit ownership" and ledger COMMIT-3. -
fix(claude-code): tokens-per-second sanity: a response-side attachment introduced in Claude Code builds from 2026-09-26 sat in the timing start slot and collapsed generation spans (rates up to 127,667 tok/s). A table of response-side attachment types plus a strict-before rule fix the span (live 7-day max 229, no row at or above 500). Rows stored with the old rule are corrected when their transcript is re-parsed.
-
feat(proxy): the Claude Code prompt id (
x-claude-code-prompt-id) is recorded per proxied turn (agent migration 139, node-local) and the next-message predictor groups by it;observer claudeenables Claude Code's gateway hint headers only when routed to Observer's proxy and never over your own value. Codex: a Responses websocket upgrade is answered 426 so Codex falls back to captured HTTP;/v1/realtimeroutes to OpenAI instead of Anthropic;observer doctor codexgainscodex.proxy_routeand reports a managedrequirements.tomlprovider. The org AI gateway forwardsanthropic-*headers. -
fix(cursor): an unfinished Cursor turn (quit mid-answer, or every retry failed) records evidence and a precise reason on the node page, the org drawer and
observer doctor cursor(cursor.usage) instead of a number: no local artefact holds its billed usage. Auto-mode turns record the model Auto routed to per request; placeholder models (default,auto) never overwrite a concrete session model; hook input nets both cache buckets (cache writes were billed twice). cursor-agent 2026.09 also runs Claude Code's user hooks with Cursor payloads; the Claude Code receiver now ignores those (no duplicate prompt guard, no rows mis-tagged as claude-code). -
fix(adapters): Hermes schema 30 auxiliary-call spend is captured on both the hook and database paths. Crush's token counters are the last step's context size, so only one-step sessions keep token counts; every other Crush session keeps a token row with its model and Crush's own cost at 0/0 tokens (reliability unknown), and
observer backfill --crush-rescancorrects rows stored before. New tool-name mappings seen live or in vendor source (for example OpenCodequestion-> ask_user, Clinelist_code_definition_names, Zedgrep/fetch/spawn_agent, Kimi plan mode and task tools). -
feat(mcp): MCP calls made through the node relay are tied to their session for every client, not only Claude Code: a third, unanchored correlation tier (always labelled
inferred, read-side only, retroactive, ambiguity shown rather than guessed). Protocol traffic (tools/list, notifications) never claims a tool action and attaches at session level; the method reaches the org so the drawer shows the same fields as the node (server 181 / pg 0047). -
feat(ide):
observer ide <id> [project-dir]launches an IDE or desktop app through the same path as the dashboard's GUI launch and prints an honest per-agent routing outcome (vendor-hosted inference such as Cursor's own models, Antigravity, Kiro, Qoder, Devin / Windsurf or Grok Bot cannot be routed and is reported so). Live traffic proof is still owed for VS Code, JetBrains, OpenCode Desktop and Goose Desktop (steps indocs/proxy-wrappers.md). -
feat(shell-wrap): command wrapping, default off:
observer shell-wrap status|preview|enable|disableand a Settings -> Terminal "Command wrapping" card put PATH shims first so typingclauderunsobserver claude(per-tool opt-in;allmeans installed CLI tools only). One marked block in bash / zsh rc files, a fish conf.d drop-in or the PowerShell profile (never auto-created), an exact preview, byte-for-byte undo, recursion guards so no launcher resolves a shim. Onobserver starta shim whose observer binary was moved or deleted is re-pointed at the running binary (a still-runnable different binary is kept); the PowerShell profile resolves the real Documents folder. Ledger SHELLWRAP-1. -
fix: small live-verification defects: the org session quality card's newer-action count is derived like the node's (it was always 0); the goose watcher no longer logs "caught up dropped writes" every 2 s for a database scanned by row watermark;
observer doctor <tool>defers the whole-database quick_check (--integrityforces it); the Cursor "no finish hook" note no longer tells you to runobserver initwhen the hooks are already registered. -
chore(build):
web/distandweb2/distare no longer tracked (the threego:embedbundles stay committed, sogo installand the Docker builds are unchanged), every dist tree is marked-diff, and source maps stay out of the embeds; a rebuild no longer produces a multi-megabyte diff that agents such as OpenCode copy into their session stores. Storedraw_tool_outputis capped at 1 MiB at every writer. -
fix(security): a review of what earlier reviews had not covered (
docs/audits/security-review-2026-09-27.md; 3 High + 9 Medium found, all High and 7 Medium fixed with regression tests): the proxy refuses browser-shaped requests (a web page can no longer drive it cross-origin; CLI, SDK and editor clients are unaffected); the guard evaluates Monitor, PowerShell and Grep tool calls; a truncated PreToolUse payload asks instead of allowing in enforce mode;key_poolrotates only credentials in the pool; Gemini API keys are redacted; the org gRPC receiver authenticates before decoding; tree-sitter parsing runs under deadlines; a repository symlink into your home directory no longer leaks the target throughget_project_guidance; node database files are restricted to 0600 when opened. The rest is ledgered as SR27-*. -
feat(sandbox): sandboxed terminals are contained (SR27-SBX-1): each sandboxed launch gets its own network namespace with the tier from
[terminal.sandbox].egress(internetdefault,proxy_only,none, orhostwhich restores the old shared namespace). A host helper serves the observer proxy and an egress gateway over sockets bound into the sandbox, so launcher URLs are unchanged and the dashboard on:8081is unreachable from inside; the gateway refuses loopback, link-local (incl. 169.254.169.254), multicast, the host's own addresses and private ranges (RFC 1918, CGNAT, IPv6 ULA and site-local) unless listed in[terminal.sandbox].egress_allow_cidrs. Every tier runs in a private PID namespace; host sockets under/run, WSL interop and agent environment variables are masked; Observer's secrets and the attach socket are hidden; daemon config, guard policies, shims, each tool's hook and MCP config and the workspace.git/configand hooks are read-only (a missing protected path gets a read-only placeholder) unlessallow_tool_config_writes = true. A host that cannot create a network namespace refuses the launch (netns_denied), never a silent fallback. Linux and WSL2 only, opt-in as before; residual risk in ledger SR27-SBX-2, seedocs/sandboxed-terminals.md. -
fix(harness-gateway): the codex adapter runs codex with its built-in tools disabled (exec, shell, view_image and apply_patch calls return unsupported, web search off, the default-off features explicitly disabled), an allow-listed environment and a per-session private home;
@openai/codex-sdkand@openai/codexare pinned to exactly 0.147.0 (the disabled list is re-grounded on every bump), and turns are serialized per session with the codex home disposed only after a running turn ends (SR27-C2). -
fix(dashboard): the node dashboard's Origin check compares scheme, TLS, host and port with the request's own Host (loopback aliases equal) instead of the host alone (DASH-ORIGIN-1).
-
ci: third-party GitHub Actions in secret-holding jobs are pinned to commit SHAs (tag kept as a comment; Dependabot keeps them current) (SR27-SC1).
-
Price snapshot: 2026-09-17 (aws us-east-1, azure eastus2, gcp us-central1) — the dated
three-cloud price snapshot everyobserver-org deploy planestimate in this release is
computed from (plan v2.1 6.9;scripts/verify-price-snapshot.sh --lineprints this line and
scripts/release.shrequires it in a final tag's section).
Downloads
Pre-built binaries for each supported platform are attached below. Linux variants bundle antigravity-bridge.exe next to the observer binary for WSL2 users of the Antigravity adapter.
| Platform | Asset |
|---|---|
| Linux x86_64 | observer-v1.34.0-rc.10-linux-x64.tar.gz |
| Linux arm64 | observer-v1.34.0-rc.10-linux-arm64.tar.gz |
| macOS x86_64 (Intel) | observer-v1.34.0-rc.10-darwin-x64.tar.gz |
| macOS arm64 (Apple Silicon) | observer-v1.34.0-rc.10-darwin-arm64.tar.gz |
| Windows x86_64 | observer-v1.34.0-rc.10-win32-x64.zip |
Verify with sha256sum -c SHA256SUMS (or shasum -a 256 -c SHA256SUMS on macOS) from the directory containing the downloads.
Also available via npm: npm install -g @superbased/observer@1.34.0-rc.10
Org server (Teams)
The self-hosted org server is an enterprise-licensed product distributed from SuperBased's private container registry with a per-customer pull token issued with your enterprise licence; its release assets are not attached here. Contact sales for a pull token. The pull-and-verify recipe for your exact release is the README.md of the deployment bundle (observer-org deploy export).
Enterprise updates
This release publishes on the edge channel.
Each agent archive carries a detached vendor signature (<archive>.sig, raw Ed25519 over the archive bytes) and the release ships a signed update-manifest-edge.json. Self-hosted org servers consume them with:
observer-org update sync --version v1.34.0-rc.10
observer-org update publish --channel edge --version v1.34.0-rc.10For a disconnected server, download observer-v1.34.0-rc.10-airgap-bundle.tar (archives + signatures + SHA256SUMS + the signed manifest + provenance), carry it across the gap, and run observer-org update import --version v1.34.0-rc.10 --bundle <dir>.
Supply chain
A CycloneDX SBOM for the agent is attached: observer.cdx.json.
SLSA Level 3 build provenance for the binaries is attached below as a *.intoto.jsonl attestation. The build runs on the private origin repo, so pass that as the source when verifying an extracted binary with slsa-verifier v2.7.0 or newer (older versions fail with unexpected tlog entry type: expected intoto:0.0.2, got dsse:0.0.1):
slsa-verifier verify-artifact ./observer \
--provenance-path *.intoto.jsonl \
--source-uri github.com/marmutapp/superbased-observer-private