Open work

The one live list of what is being built, what comes next, and what is waiting on a decision. Last reconciled against main at f4c6fa7f (2026-10-16).

The rule. A shipped item is deleted, not struck through: its record is the CHANGELOG entry and the PR. A wrong row is corrected in place, never answered by a new row beside it. Nothing in Now or Next is marked done. Feature PRs do not edit this file; the coordinator reconciles it after merges, because every PR editing its own row made every PR conflict with every other. scripts/check-open-work.sh (CI job open work, not required) runs on main and on a PR that edits this file, and fails when a PR listed under Now has merged or the stamp above is not on the branch. Red on main means reconcile.

History (the dated programs, audits and dispositions this file carried until 2026-09-29) is in Open Work 2026-08-25 to 2026-09-28. Direction is in Roadmap; what shipped is in Capabilities and CHANGELOG.md.

Before anyone deploys

No blocker is open. B2 (the stack's prod values pulled the dev image), B3 (working default credentials) and B5 (deploy paths that pointed at a missing tag or the wrong image) were fixed by #1156, and B6 (the stack's bundled datastores pulled images that no longer exist) by #1172. B1 (the pins named a release from before the cross-tenant fixes) and B4 (the ARM64 page ran v315.0.0 with auth off) were fixed by the v413.0.0 tag and the pin bump after it: every deploy path and install command pins v413.0.0, docs/Pi.md runs it with auth on and maidan init, and scripts/check-deploy-pins.sh (CI job deploy pins) keeps fifteen pins on the newest tagged release. The :dev images in compose.yaml and the charts' default values.yaml are built from source on purpose. Pointing anyone at a deploy is part of the launch, which is the maintainer's call.

Do not tag a commit whose push CI is red or unfinished. open work is not a required check, so a red open work alone does not block a tag; the eight required checks on the tagged commit do.

Now: in flight

Merge order matters where one PR builds on another; the column says so. A lane marked Active is being built in the coordinator's session from a local worktree: an agent outside that session does not start it, and takes a row of its own instead. No lane is active. Work left in stopped lanes is on wip/ and wip/rescue-* branches, named in the Next items it belongs to. Rows without a PR number are being built and get one when opened. The coordinator's merge loops run in its own session; whoever merges without them follows the merge rule in CLAUDE.md (all eight required checks on the exact head commit, --match-head-commit, and every CodeRabbit comment answered) and, before merging, builds the PR on current main if another PR merged since its CI ran.

PRWhat it doesState (2026-10-13)Merge after

Next: ranked

The launch path, ranked by what the launch needs first. The launch is open source plus a hosted service at maidan.world (decided 2026-10-12): the hosted rows (Next 24 to Next 28) come after the OAuth server people connect through, and the list closes with the launch release and its gate (Next 29). The directory listings follow the launch, on the maintainer's go. An item enters this table with acceptance criteria and a check that shows it is still open. "Thread" numbers refer to the 2026-09-29/30 enhancement thread, whose dispositions are recorded below.

#ItemSizeAcceptance criteriaOpen becauseDepends on
33Agent swarm coordination (the swarm design relayed on 2026-10-13; Swarms); the swarm runs against a local stack, not the hosted instances (decided 2026-10-14)M, as several PRsMany agents work one repository without colliding or merging unreviewed code. A claim carries a footprint (paths, globs, crates, lanes, branches) and a lease TTL, and claim_next defers a thread whose footprint overlaps a live claim. Results reach Linear issues as well as GitHub and Slack. Egress works with outbound credentials alone. A ready agent pull request is enqueued into its repository's merge queue only at the head the change flow delivered, and the change flow never pushes to a queued one. An operator can pause one repository: claim_next then defers every thread whose footprint names it, and work already claimed finishes. Then build-slot admission: a per-lane and per-instance cap on concurrent heavy builds, so 3 to 15 workers share one machineShipped: footprints (#1397), the merge queue (#1399), pause (#1401), the repo filter (#1406), slots (#1407), intake footprints (#1409), deferral reasons (#1412), ramp metrics (#1415), the swarm panel (#1416), close-on-merge (#1426), change notices (#1428), producer cancel (#1429) and squash-rebase rounds (#1445). In review: task attributes with size, acceptance and priority at intake (#1427). To build: planner fan-out (#1421, after #1427). Three Pi workers run on the local stack (2026-10-16)—
23OAuth authorization server (connected apps Lane 8, decided 2026-10-08)L, seven phases, discovery and metadata firstFull OAuth 2.1: discovery and metadata, then the flows, with consent in the /ui console, public and confidential clients, client metadata documents and pre-registration and no dynamic registration. Held to: metadata documents fetched only through the egress guard, PKCE S256 only, exact redirect URIs, rotating refresh tokens whose reuse revokes the family, tokens bound to the MCP resource (RFC 8707), iss on responses (RFC 9207), a consent page that cannot be framed, grants that never exceed the member's capabilities, and a first milestone that advertises no flow it does not serve. The research is committed under docs/archive/ before phase oneP0 to P3 shipped (#1324, #1337, #1364, #1367: refresh rotation, lineage revocation, /oauth/revoke, resource binding, RFC 6749 errors). Then P4 (each member lists and revokes the grants its apps hold, in the console), P5 (rate limits on the new endpoints, and a contract that fails on a grant wider than its member) and P6 (a recorded run from real MCP clients against the demo host). Clients identified by a client metadata document cannot reach the token endpoint yet: oauth_grants.client_id and oauth_authorization_codes.client_id reference oauth_clients, where those clients are never storedThe credential rule shipped in #1325, so an OAuth token cannot accept a gate
25Per-tenant key custody (the hosted gate from thread 52)MEach workspace's message keys are wrapped by a key of that workspace's own, not by the one instance key, and that key can live in a KMS behind an interface with a local implementation and one cloud KMS. Erasing a workspace destroys its key. Rotating it re-wraps the message keys without re-encrypting the messages. An operator holding the database alone cannot read a workspace's content. Tested on both backends, with a two-tenant test that one workspace's key opens nothing of another'sThe hierarchy shipped in #1394: a key per workspace, wrapped by the instance KEK, wraps its message keys; erasure deletes it; rotation rewraps key rows only; a two-tenant test on both backends. The cloud KMS custody is open (custody names the wrapper, local today)—
24The hosted deployment at maidan.worldMOne origin serves the console, the API, MCP and OAuth (MAIDAN_PUBLIC_ORIGIN), with TLS, on the domain layout decided on 2026-10-12: maidan.world serves the console, the API, MCP and OAuth from one origin, docs.maidan.world the docs, dev.maidan.world the staging instance running main, and try.maidan.world the demo instance (Next 12) running the release. Each deploys from the repo's own Helm chart or compose file and its pins, keeps point-in-time backups with a restore drilled on it, routes alerts to a person, and has a status page. The runbook is in docs/Production.mdHosting is decided: Cloudflare Containers, Neon and R2 (Decisions, 2026-10-13). dev.maidan.world runs main, deployed by the deploy dev workflow on every server change (#1386): a Worker in front of one container that sleeps when idle, Neon Postgres, R2 artifacts, scanner probes answered at the edge. Not yet: try.maidan.world, maidan.world itself, the docs site, point-in-time backups with a drilled restore on Neon, alert routing and a status pageNext 25 before any stranger's data
27Usage metering and the free allowanceMEach workspace's usage is metered where it costs: stored bytes (database rows and artifacts, the media quota of #1366 among them), requests and MCP calls, WASI execution time, embedding calls and outbound deliveries, into one per-workspace ledger with a daily rollup. An instance sets a free allowance per meter. Past it, a workspace is marked over its allowance, the console and the operator API show it, and its admins are told. Nothing is cut off or billed at launch: the hard limits that exist (quotas, rate limits) stay as they are, and billing on the ledger comes after launch (Later L)The usage ledger prices model calls (Program C, #1242), and the media quota counts artifact bytes (#1366). Nothing else is metered per workspace—
28Hosted abuse controlsS to MSign-up and invite endpoints are rate limited per address and per email domain. An operator can suspend a workspace, which refuses its tokens and sessions and keeps its data, and lift the suspension, both audited. Outbound deliveries from hosted workspaces stay behind the egress guard with per-workspace limits. Each is tested, the suspension with two tenantsPer-workspace rate limits and fairness exist (#1153), and the waitlist, invite and sign-up endpoints are rate limited per address and per email domain (#1425). There is no workspace suspension yetNext 26
14A validated version before any submission (connected apps, Lane 9's hint and title pass, pulled forward by the maintainer on 2026-10-04)MEvery tool carries explicit readOnlyHint, destructiveHint and openWorldHint values and a title, each value with a one-line reason a reviewer can check, and a contract test fails when a tool lacks one, so new tools stay compliant. Every listing has a validation record before anything is published or submitted. The package installs on a clean machine against an instance on the release. Every tool in the listed surface (the full 246 or a curated profile of about twenty, chosen per listing) succeeds with valid parameters and returns an actionable error with bad ones. The listing's example prompts run through the platform's own model and pick the right tools. The reviewer token outlasts the longest review wait. The record names the commit and image digest it validated, and any change to the listed surface re-runs it before a resubmission. The four tools that mix reads and writes stay single tools, each a documented write, as decided on 2026-10-07. Every submission also satisfies three protocol-layer properties, audited 2026-10-05. No surface lets the supervised agent compose, trigger or satisfy its own approval. Every approval binds to a verified human identity, per-user credentials at minimum. The close gate stays server-side and durable. A model may decide an approval only through Next 17's credential-bound path: a browser session, approval:grant, or a confirmation the person gives outside the model. Elicitation is a complement, not a foundation. It is supported in Claude Code, Codex CLI, Cursor, VS Code and Copilot, and GitHub Copilot CLI, not supported in ChatGPT web or Gemini CLI, and unverifiable for claude.ai. Form mode takes flat primitives only, so evidence does not fit, and client-side approvals are non-binding by construction, so elicited answers are advisory and the close gate stays server-side. Every directory listing carries the trust-model sentence in its materials and tests. Provider-rendered approval UI is untrusted display, the Maidan console is the trust root, and an approval whose evidence the human did not see in the console is provisional. Each release re-runs the validation record and re-curates any curated tool profile, owned by whoever cuts the releaseThe annotation half landed in #1264: every tool carries readOnlyHint, destructiveHint and openWorldHint with a one-line reason, enforced by a contract test. Still open: no listing has a validation record. The clean-machine install, the example-prompt runs through each platform's model, and the reviewer-token parts are unbuilt. #1284 made every tool group answer a valid call and name the argument a malformed call got wrong, through the official Inspector, and the request half of this row's error bar holds only for arguments that do not parse. The four tools that mix reads and writes (claim_next_thread, claim_next_workspace_thread, mark_inbox_read, open_dm_conversation) stay single tools as documented writes, decided 2026-10-07 and held by tool_annotations_contract (#1281)The maintainer's go for any submission. It gates every publish in Next 9 to Next 13 and Next 15 to Next 16. Its validation record runs on the connected-app dev and test harness that landed in #1280 to #1289 (the dev instance, the request log, the Inspector probes per tool group and the client matrix)
17The ChatGPT inline approve card (the rest of the connected-app dev and test program)S to MAn MCP Apps UI resource (ui://, text/html;profile=mcp-app) renders the gate inline in any host that implements MCP Apps, ChatGPT included, and decides through the host's tools/call to approval_decide (#1332), so it follows that tool's rule: a direct accept only with approval:grant below the workspace's confirmation threshold, otherwise the one-time console link. The gate's card and audit row name the deciding client from the credential first (a registered OAuth client), then the client's own clientInfo shown as self-reported, then none (both decided 2026-10-09). Tested in ChatGPT against a dev instance before any listingThe card shipped in #1343 and the link's lifetime is a workspace setting since #1344. It has not been tried in ChatGPT; dev.maidan.world is now a public origin to try it against—
13Adoption and per-user connect recipes (connected apps Lane 5 folds in here)S to M eachAn OpenHands claimant recipe. Provider recipes I2 to I6 (Providers). The official third-party SDKs run as clients in CI. Connect recipes for Claude custom connectors, Perplexity, grok.com and Gemini custom MCP (US, 18 and over, a personal account with Keep Activity on, and the skills surface that replaces Gems (Gems move to Settings on November 17, 2026 and stay usable until Google removes them), each tested against a real instance with a manually minted, scoped and expiring token, and each noting that an authorization server would replace it. Page views per recipe are the proxy metric. The recipes follow the paths verified on 2026-10-06. claude.ai through Customize, Connectors, Add custom connector (Free allows one). ChatGPT developer mode under Settings, Security and login, then the Plugins page, where a schema change is picked up with the refresh control rather than by re-adding the server. Claude Code with claude mcp add --transport http. Grok through grok mcp add --transport http and through the Responses API, whose MCP tool declaration carries the token in its authorization field. Muse through a conversational custom connector, a manual walkthrough logged with the app version and date. Grok's custom connector (New Connector, Custom, a server URL and a static bearer, available to all Grok users per docs.x.ai/grok/connectors) is the cheapest consumer test path. Gemini Apps custom MCP is limited to Gemini Spark users within Spark tasks (official help), so that recipe says so. claude.ai install links (?modal=add-custom-connector with a name and URL) are a documented way to share a connector without a directory, and the recipe uses them for a self-hosted instance's own URLNone of the recipes exists, and only the MCP Inspector runs, report-only. No doc names these four clients (search of docs/, checked at 3d0a8d10). Moved up from the bottom of Next, because the strategy's lane order puts the connect recipes in the fast track and the fold rule puts them in this rowNext 24's public origin for the hosted clients (claude.ai, ChatGPT, Grok). Claude Code and other local clients need none
12Listing asset pack and the demo instance (Lane 4)S for the pack. The demo instance is hosted under Next 24Short and long store descriptions that lead with the room, not the tool count, and name both the hosted room at maidan.world and the self-hosted path. An icon set (a square of at least 48px, a 400x400 PNG). Name and logo clearance before any submission. Screenshots only where a directory requires them, taken by the capture script from #1353. The demo instance runs the release at the demo host (Next 24) with a seeded workspace that resets between reviewers, a reviewer token per directory whose expiry outlasts the longest review wait, rate limits and seeded-room isolation against abuse, and a token prefix per listing so connects attribute to the lane that earned them. The privacy policy, terms, support contact and data statement are the maintainer's, prepared outside the repo for launch (decided 2026-10-12), and each listing links themNo asset pack exists, and no demo instance runs. Tokens already take an expiry (expires_at) and a demo seed exists (scripts/demo-board.sh), so the demo work is hosting, reset and abuse limits, not new token codeNext 24
30Launch polish: performance and the UI auditM, as several small PRsThe performance Tier 0 batch (response compression, ETag revalidation on /ui assets, the notices-query index with EXPLAIN before and after, a capped live feed) and the P2 items of the 2026-10-03 UI deep dive, each its own PR with a testCompression (#1378), ETag revalidation (#1380) and the notices index (#1381) shipped; the capped live feed shipped (#1385), so Tier 0 is done. The UI deep dive's P2 items are open—
29The launch release and its surfacesMA release cut from a main whose push CI is green, with every deploy pin on it, is the launch candidate. The docs site serves from the domain layout. The README and the site lead with the hosted room and the self-hosted path side by side. The maidan-launch-1.0 gate test (Roadmap, Gates) drives the hosted path end to end: an invite, sign-up, a workspace, an agent connected through OAuth from an MCP client, a task claimed, reviewed and closed, and the usage it meteredv413.0.0 predates the OAuth flows, the hosted rows and the week's fixes, and no launch gate test existsNext 23 to Next 28, Next 30 to Next 32
11MCP registries and catalogs (Lane 3)S, 2 to 4 days plus review waitsThe same-day entries first. The official MCP registry through mcp-publisher with the OCI package type on the published image, then a request to partnerships@github.com for the GitHub MCP Registry and VS Code's one-click install. Glama (a repo topic and glama.json). One line in the classic awesome-mcp-servers list. A Cline marketplace issue with a 400x400 PNG icon. Smithery's URL path once the demo endpoint exists (Next 12), with a static card at /.well-known/mcp/server-card.json and an unauthenticated MCP request answered 401, confirmed on the public endpoint before submitting. Then two async PRs, each with a retry budget. The Docker MCP Catalog (server.yaml, a tools.json that matches tools/list, and the entry variant, a remote endpoint or a container, chosen at lane time, with the Dockerfile where the catalog expects it) and the ToolHive catalog (a server.json that reuses the registry's OCI block, its canonical repo confirmed at lane time). The container variant needs a first-run token flow the catalog's CI step can run without the insecure quickstart image. MCP.Directory, MCP Harbor and the Continue Hub are checked and batched if cheap. Paid listings stay out (Won't do). Each entry is prepared and validated, and none is published, filed or emailed until the maintainer's goThe build half shipped (#1373): the server card at /.well-known/mcp/server-card.json and the registry, Docker and ToolHive manifests under listings/, pinned by check-deploy-pins.sh; glama.json is on wip/listing-glama. Nothing is filed, published or emailedThe maintainer's go for any submission, on a validated release. The Smithery step waits on the demo endpoint in Next 12
10GitHub Copilot CLI plugin marketplace and the Agent Plugins 1.0 package (Lane 2)XS.github/plugin/marketplace.json and a root plugin.json carry the MCP server config and the worker and reviewer skills, built once in the Agent Plugins 1.0 shape so Next 16 (Cursor) reuses it. Installing from the public repo URL works against a local instance in a recorded run. If the npx add shorthand needs an npm package to resolve, the lane publishes one and records it here. The plugin is free, and its description says production is self-hosted. It is built and validated on a branch and merges to main only on the maintainer's go, because a marketplace file on main is itself the listing. The walkthrough mitigations are built in. Review decisions route through elicitation, which the platform supports, and the bundled preToolUse hooks provide client-side checks for the plugin's approval workflow. They are not an authorization boundary. The server-side claim gate and durable close gate remain authoritative. Per-user tokens ship behind a stdio shim, since Agent Plugins 1.0 passes remote config literally with no environment variable expansion. The plugin does not carry the MCP server, which Copilot CLI adds separately with copilot mcp add, so the recipe and the validation record cover both. plugin.json declares the Agent Plugins 1.0 $schema. The built plugin waits on wip/copilot-plugin until the maintainer's go (#1268)Built and validated on wip/copilot-plugin (#1267); reverted from main by #1268 to keep it unlisted. It merges to main only on the maintainer's go, because a marketplace file on main is itself the listing, and nothing is published or submitted while Maidan is being built (decided 2026-10-06). GitHub's Copilot CLI plugin docs describe a marketplace file in a public repo with no review step (docs.github.com, observed 2026-10-03). The worker and reviewer profiles it packages are on main (#1240). Trust-paradox walkthrough, audited 2026-10-05. Per-surface verdicts are in the walkthrough synthesis kept outside the repoThe maintainer's go for any submission, on a validated release
15Muse connector submission, shadowing a sibling app (Lane 6)S. 1 to 2 days after Next 14, plus one assumed rejection and resubmit cycleThe form materials (the strategy's description and example prompts, the demo endpoint, the API-key choice on a reviewer token from Next 14) are prepared and held until the outcome of the maintainer's the sibling app submission, with a time bound set when the lane starts. A the sibling app rejection on the shared API-key auth model re-scopes this row to OAuth with PKCE behind the parked authorization server, or parks it. A the sibling app rejection on the sibling app-specific grounds changes nothing. Before submitting, a supervision-session walkthrough names the capability profile the listing authenticates as, the session topology (the platform's agent as the worker, or outside workers with the listing as the reviewer's surface), and where the human review happens. A listing on one operator token does not promise the reviewer as a separate trust role. The first review round is also the test of whether the room sells in a directory. Re-check at lane time. The form fields and API-key acceptance are corroborated by four third-party submitters and documented nowhere by Meta, so the maintainer resolves them first-hand from the the sibling app form. If the form takes the API-key shape, the field list locks. If review refuses it, the re-scope rule above applies. The work-email login gate and the Stripe payments question are third-party reported and unverified. The submission itself waits on the maintainer's go and on Next 14's validation record. The submission materials declare that durable approval gates resolve only in Maidan's console, and the listing copy does not promise in-Muse supervision. The audited walkthrough verdict is that supervision does not survive in the as-shipped shape, because no push channel or inbox is documented and a shared key breaks separation of duties. The forced console bounce is the strongest enforcement guarantee available there, since Muse cannot wrongly resolve a durable gate. How the human learns of a waiting gate stays an open lane-time problem, and so does the Meta form's end-user API-key setup flow. The maintainer gave a go on Meta's Connector Terms §3.1(c) on 2026-10-06, accepting that Meta may use connector content and user interaction data, including who approved what, to improve Muse. The submission uses per-user scoped tokens, never one shared admin bearer, since Meta's guideline §4.4 asks each user's data to be isolated, a thin tool set Meta can classify (read, write, sensitive write), a dedicated reviewer account, and the trust-model sentence. Meta's connector guidelines and terms are now public (muse.ai/platform/docs, muse.ai/platform/terms, checked 2026-10-06), so the review criteria are no longer unknownmuse.ai/platform is live (fetched 2026-10-04), and Meta publishes no criteria, SLA or fees. Maidan has no listing. Trust-paradox walkthrough, audited 2026-10-05. Per-surface verdicts are in the walkthrough synthesis kept outside the repoNext 14, the the sibling app outcome
16Cursor Marketplace, manual-token shape (Lane 7)S. 2 to 4 days after Next 14, plus one assumed rejection and resubmit cycle (1 to 2 weeks of review wait each, third-party reported)The Next 10 package, or a .cursor-plugin/plugin.json, per https://cursor.com/docs/plugins. The listing states its auth honestly as a token the user configures at install, scoped by capability and expiring, never a non-expiring admin token. The OAuth upgrade waits on the parked authorization server. Terms and privacy policy from Next 12 visible in the listing, accurate metadata, no training on user content, free to users, and a token prefix per listing for attribution. A supervision-session walkthrough, as in Next 14, before submitting. Updates are batched, because every update is re-reviewed. Re-check at lane time. The publish form at cursor.com/marketplace/publish renders only through JavaScript, so its fields are UNVERIFIED. The submission waits on the maintainer's go and on Next 14's validation record. The identity design is fixed before shipping, either two tokens with separated duties or a declared worker-only listing with approvals in the console. The ambiguous single token does not ship, because the walkthrough shows it manufactures false approvals. Background elicitation notifications are re-checked at lane time, since Cursor 1.5 added OS notifications when input is required. Cursor's solo-user plugin variable flow stays an open lane-time question. Cursor 2.6 renders MCP Apps inline (official changelog), so the board and an approval card can show in chat, and the card links to the console, where the decision is made. Lane testing uses Pro accounts, since several October 2026 sources agree the Hobby plan excludes MCP. Every directory listing carries the trust-model sentence in its materials and tests. Provider-rendered approval UI is untrusted display, the Maidan console is the trust root, and an approval whose evidence the human did not see in the console is provisionalNo Cursor package exists (checked at 3d0a8d10). The MIT license clears the publisher terms' permissive-only bar (https://cursor.com/marketplace-publisher-terms). Minting a token needs token:admin (crates/maidan-server/src/routes/token.rs), so the self-service token the strategy copies from its teardowns does not exist, and an admin mints each user's token. Trust-paradox walkthrough, audited 2026-10-05. Per-surface verdicts are in the walkthrough synthesis kept outside the repoNext 12, Next 14

Connected apps (Next 10 to Next 17, and Later CA). The no-authorization-server fast track the maintainer chose on 2026-10-03, in the strategy's lane order, with Lane 9's hint pass pulled forward as Next 14. Nothing is published or submitted to any directory, catalog or registry until the maintainer says go (2026-10-04), and never without Next 14's validation record. Until then a lane is done when it is built and validated. Every listing row depends on a validated release and the maintainer's go, because every listing points at a release, and the listings follow the launch. Each directory size includes one assumed rejection and resubmit cycle. No estimate is discounted for the the sibling app work, which transfers the OAuth protocol mechanics, the privacy policy's section headings, the Muse form mechanics and the sibling app's review outcome as an early signal, and nothing else (not the consent design, the reviewer identity path, the policy's substance, the crypto-shredding tail or the runbooks). Each lane is judged on its own. A lane whose connects reach the demo endpoint ships a token prefix per listing (half a day to a day each), so attempts attribute to the lane that earned them. The self-hosted lanes (Next 11, Next 12, the registry and image entries of Next 13, and Next 15) cannot see connects by design, and are judged on proxies, namely registry pulls, install counts, topic-driven GitHub traffic, recipe page views and any visibility a directory reports. A hybrid directory lane is judged on reported visibility plus those proxies, because its real users self-host. A near-free catalog PR promotes on acceptance. A heavier later lane promotes when two directory lanes each hold at least 25 attributed connects a week, on a four-week rolling average or in three of any four weeks, after scanner and reviewer traffic is filtered out, or when it reaches an audience the directory lanes cannot. The AWS lane and the IDE wrappers promote on acceptance plus one clean end-to-end install. The 25 is a starting guess, recalibrated after 90 days of data and recorded here. A lane is killed when a rejection has no remediation path, when a queue stalls 90 days with no response and no escalation, when 60 days live bring zero attributed connects on a hosted lane of size M or larger, or on the day a platform rule removes its fit. A killed lane stays recorded with its reason and date. Review-gated lanes are judged after 30 days live or two review cycles, whichever is later, and zero-review lanes after 30 days. Support tickets are tagged by surface at intake. Cursor and Anthropic re-review every update, so updates are batched, and each one re-runs Next 14's validation record. The strategy master is the connected-apps research of 2026-10-03, kept outside the repo. The supervision-session walkthroughs the directory rows require were walked and audited on 2026-10-05, with per-surface verdicts in the walkthrough synthesis kept outside the repo. ChatGPT, Cursor, Gemini CLI and Copilot CLI survive with mitigations. Claude connectors and Muse do not survive as shipped. How a human learns of a waiting gate is unbuilt on every surface except ChatGPT Work chats, where MCP Events are the documented wake-up path, and whether any directory surface has a push channel for connector events is open. Cursor 1.5 added OS notifications when input is required, which re-opens that question for Cursor without resolving it. Every listing, parked ones included, carries the three protocol-layer properties in Next 14.

Measure before scheduling: the per-response query count (F-51); whether the workspace context pack filters before it builds; the search deny-set query; the board's full re-render on large channels (thread 17); catch_up page cost as the event log grows (thread 18).

Found by the 2026-10-04 lanes, small enough to fold into the nearest PR. #1250 left an events-behind lag gauge undone and its new alert cases not yet run through promtool.

Found reviewing the installed-app OAuth flow (2026-10-08), small enough to fold into the nearest PR. exchange_app_code consumes a code before it checks redirect_uri and the verifier, so anyone holding a stolen code can burn it. The fix checks every binding, then consumes atomically, and app_oauth_e2e, which asserts today's order, changes with it. The token it mints has no expiry, and the exchange never authenticates the app, so PKCE, which the flow makes optional, is the only proof of possession. docs/OAuth.md carries all three as acceptance criteria for the new server.

Found running Claude clients against a local Maidan (2026-10-07), small enough to fold into the nearest PR. Claude Code passed discovery, search, post and an ordered search-then-post against a seeded workspace, and Claude Desktop passed discovery and search before the run stopped, each call confirmed in the request log. Search results carried ids but no names, so the model reported ids to the user (fixed by #1300). post_message needs a thread, so "post to #general" costs two lookups and is ambiguous in a channel with several threads. Claude Code speaks 2026-07-28 (server/discover, per-request _meta) on every call, which makes Next 8 a live client problem. A managed third-party Claude Desktop reads ~/Library/Application Support/Claude-3p/, not Claude/. claude.ai and Desktop custom connectors still need a public HTTPS URL, which the anonymous dev mode and MAIDAN_ALLOWED_HOSTS now make possible on the maintainer's go. The dev-instance recipe in docs/Clients.md names MAIDAN_ALLOWED_HOSTS.

Found by the #1247 and #1248 lane (2026-10-04), small enough to fold into the nearest PR. compose.yaml hides the root-owned /data volume problem because it stores artifacts in MinIO. A first install that collides with a hand-made app:<slug> member still answers with the generic handle conflict.

Found by the 2026-09-30 lanes, small enough to fold into the nearest PR: the store's *_audited methods do not check that an audit's scope matches the workspace they write in (#1134); the request-layer mutation row stamps the token's workspace, not the path's, for a bypass caller (#1134); a receiver that echoes a secret back in a slash response puts it in metadata.slash_response (#1140, documented); the retry budget is per replica and does not bound first-attempt floods (#1122, documented); and crypto_shredding blob_reap::sqlite_backend can fail with database is locked in the coverage job (seen on #1155, whose change touches no store code).

Later: by program

One line per item, promoted into Next when it gets acceptance criteria.

  • R — resilience: chaos steady-state checks; native TLS on the gRPC listener (#1114 requires an acknowledgement instead).
  • V — verification: stateful model tests beyond the claim lease; Kani over idempotency keys and FSM totality.
  • D — Postgres operations: a durable retry for orphaned artifact blobs: DELETE /artifacts/{sha}, workspace purge and media expiry each log a failed blob delete (purge.orphaned_blob_not_deleted) and move on, leaving unreachable bytes, so a pending-reap row written with the erase or a storage reconciler should finish them; rebuild-derived --verify (re-fold the notification ledger, follow counts and inbox cursors from the log, with a drift metric); XID-age, bloat, WAL and replication-slot metrics; a pool-topology guide; a UTF-8 pin.
  • B — protocol conformance: snapshot tests over normalized MCP, A2A, OpenAPI and audit shapes, so wire drift is a reviewed diff.
  • S — security: thread_access::readable_thread requiring the reader to be a member of the thread's workspace, so the store predicate holds without each caller pinning the workspace first (search, the explorer and the context pack all do today); authority_audit_contract over every crate and example with its two carve-outs (maidan init, the Playwright harness) named, so a call outside the two watched crates cannot slip past (thread 14b); threat-regression gates (each Threat-Model row names its test) and a per-PR threat-model delta; token TTLs with DPoP or mTLS binding; audience-bound step-up auth for sensitive MCP tools; an over-permission scan of the MCP surface; a provenance label on content from other tenants, tools and external sources; miri over the unsafe in dependencies.
  • E — compliance: read-time PII masking on messages, content blocks and audit metadata; scheduled key rotation and a key-age policy.
  • O — observability: a buffered, redacted collector pipeline with a tested loss contract; opt-in tokio-console; a named p99 on the fan-out paths; operator views.
  • F — search quality: reranking (RRF or a cross-encoder); an HNSW recall evaluation (the m/ef knobs are pgvector defaults); a query-embedding cache; a search evaluation gate over relevance_eval.rs; a ParadeDB comparison; facet search by reference kind, result kind and event kind.
  • G — developer experience and governance: a fitness-function catalog; semver checks for the SDKs; a glossary-grounding lint; active benchmarking with k6; a devcontainer, pipeline parity, typed config, a cross-build matrix and an S3 test double.
  • U — the web UI: design tokens; a code editor, log stream and DAG view; a reference-graph pane over the backlink index; an interactive OpenAPI reference; recorded demos; one-click token mint in Connect; a member last-active endpoint; cross-channel palette search; delivery and allowlist panels.
  • Federation (when federation gets real multi-peer use): a per-peer egress allowlist in place of the whole-guard MAIDAN_ALLOW_PRIVATE_EGRESS bypass, which production already refuses (thread 10); a versioned envelope contract; cross-peer causal order; verifiable-credential peer trust.
  • Parked evaluations (revisit on a concrete trigger): OPA/ABAC; Tantivy; compile-time SQL; SOPS; a CI egress allowlist; an in-flight-run drain signal; allocator and zero-copy micro-evaluations; an MCP registry policy.
  • C — context economics (Context Economics; research in archive): after C1 to C4 (C2 shipped in #1239 and #1240; C1 shipped in #1241; C3 shipped in #1242; C4 shipped in #1297 and #1299), C5 warm-then-fan-out for claims that share a prefix; C6 claim timing inside the cache TTL, with affinity for the agent whose cache is warm; C7 a batch lane for threads whose deadline has slack; C8 task fingerprints that link duplicate work and offer exact reuse of accepted results; C9 fleet harness profiles with a conformance check; C10 summarize-once digests served by sha256; C11 routing hints for self-hosted KV-aware routers; C12 model and effort by task class; C13 the A2A contextId as an affinity key and the PayerStamp as an A2A extension; MCEB-1, the pre-registered cost-per-success benchmark, after C3 and when the maintainer sets its budget.
  • UI audit P2 and the performance Tier 0 batch (UI deep dive 2026-10-03): the P2 items and Tier 0 (response compression, ETag revalidation on /ui assets rather than immutable caching without fingerprinted URLs, modulepreload, a capped live feed, the notices-query index) are recorded in the audit digest and promoted into Next as P0 and P1 land. The UI ships as a generated, minified bundle checked into the repo, with CI failing when it is stale (as with the vendored gRPC code), so cargo build still needs no Node and the bundle can carry fingerprinted URLs (decided 2026-10-04).
  • L — launch (decided 2026-10-12, with the launch-blocking work in Next 24 to Next 30): open source plus a hosted service at maidan.world, with sign-ups through a waitlist first. The hosted service is free up to an allowance, and usage past it is metered (Next 27) and billed, with billing built on the ledger after launch. Still to come here: positioning, comparison and migration pages, the in-browser playground on the demo host, and the open-core boundary written down (the room stays open source). The privacy policy, terms and trust page are the maintainer's, prepared outside the repo.
  • CA, connected apps (later lanes). Lane 8, the OAuth authorization server, is Next 23 since the maintainer's decision of 2026-10-08. The notes below are its design inputs. What exists is an installed-app authorization code exchange with optional PKCE, started by an admin call (crates/maidan-server/src/app_oauth.rs, POST /oauth/app/token). What does not is dynamic client registration, client metadata documents, OAuth metadata endpoints, a browser consent screen that maps capabilities to scopes, refresh tokens for those clients, and a 401 carrying WWW-Authenticate. When it unparks, client metadata documents are the primary path, with pre-registration for Cursor and for clients that present no document, a human stays in the consent flow, the reviewer identity path is designed in the lane, an upstream identity provider that is itself a supervised agent platform is used only if no other exists, and a 3 to 5 day security review comes before any listing depends on it. Lane 9's hint and title pass is Next 14. Its other half, splitting tools that mix reads and writes, is not done. The maintainer kept them as single tools on 2026-10-07, each a documented write. Before submitting, each directory lane chooses between the full surface and a curated profile of about twenty tools built on the worker and reviewer profiles, and runs the directory's test cases through the platform's model against whichever it lists. Lane 10, the Claude directory (S after lanes 4, 8 and 9), and Lane 11, the ChatGPT plugin directory (M after lanes 4, 8 and 9), wait on the Lane 8 revisit. Lane 10's static-headers path is a beta for a limited set of organizations, granted by invitation, and access is checked through mcp-review@anthropic.com at lane time. The audited walkthrough verdict strengthens the parked rationale. Supervision does not survive inside Claude connectors as they work today, because the surface collapses to narration plus per-tool prompts, and the directory's review rules forbid evidence-showing instructions in tool descriptions. The verdict supports the sequencing hold rather than parking on its own, and the best mitigation, MCP Apps, is build work to size before the lane is promised. Lane 11 needs a global-residency project (seven submitter runbooks say EU-residency projects cannot submit, re-confirmed in the portal), domain verification, five positive and three negative test cases, a video, and reviewer credentials without MFA. The OpenAI enterprise marketplace is a procurement and billing channel, not a self-serve plugin directory, so it is not a lane (provider research, 2026-10-06). ChatGPT's MCP Events, a signed-webhook wake-up path documented for Work chats and dots, is the one provider push channel found, and it is the natural carrier for Needs-you when Lane 11 unparks, subscribed by the user and never unsolicited. The audited walkthrough verdict for Lane 11 is survives with mitigations, and the mitigations are load-bearing, because the approval card authorizes one tool call and shows only the app and the proposed action. destructiveHint marks the call for explicit approval, which is advisory to the host and not a guarantee. toolInput stays withheld until after approval, so evidence-first ordering holds. The DevDay sidebar and panel surfaces host the Needs-you queue. The developer-mode bearer token question stays open for lane time, and no public-directory listing ships until the OAuth authorization server exists. Cutting Lane 11 and doubling Next 13 becomes the plan if Muse rejects the room as a category, if no session topology keeps supervision intact inside ChatGPT, or if the Lane 8 revisit answers skip. Lane 12, the Microsoft tracks (M to L), stays parked until the consumer lanes clear the promotion bar or a real customer in that ecosystem reopens it. Whether Microsoft's connector write actions have shipped is UNVERIFIED first-hand. Every directory lane, these included, walks a full supervision session before submitting (see Next 14) and has Next 14's validation record. The later lanes wait until the directory lanes are live and measured. AWS Marketplace AI agents and tools (M) is the exception, a procurement lane on its own bar that starts once the fast track ships. Its stateless streamable HTTP requirement on port 8000 at /mcp is UNVERIFIED. Pointing the container at the buyer's Postgres and object store does not configure the listener or the image's exposed port, so the requirement stays unverified until an image or deployment exposes 0.0.0.0:8000 at POST /mcp with test evidence recorded in Claims.md. The rest are Google Cloud Marketplace (L), Alexa with a voice adapter (M), Poe, which needs a Chat Completions endpoint (M), Kilo Code (XS, slow merges), a Workspace Marketplace Chat app (M), VS Code and Open VSX (S), and JetBrains and Raycast (S to M each). Watched, not lanes. Salesforce AgentExchange, Atlassian Rovo's announced MCP support, a Claude Code community marketplace, the end of new custom GPTs (October 26 for Enterprise, December 11 for everyone), and Anthropic's portal analytics as a visibility source for Lane 10. The dev and test program beyond Next 17 waits here. MCP JSON-RPC cassettes recorded through a proxy (agent-vcr) start only after a spike shows the proxy captures server-initiated elicitation/create, and are redacted on save. Provider-API cassettes, an unattended nightly driver for the scriptable clients (Gemini CLI, Copilot CLI, the Grok API), and an agentic-loop load test that checks rate limits under a burst of tools/list and tools/call follow. A dev-only OAuth stub for authenticated and write flows is built only when that testing starts. It refuses to boot without a dev flag, serves one synthetic identity, and is deleted, not extended, when Lane 8 unparks. Grok now has surfaces to watch, the Grok Bot Marketplace and the Grok Build plugin marketplace, though none lists third-party MCP servers for grok.com chat. Google Cloud Marketplace's AI agents category (A2A, an Agent Card and an OAuth2 code grant) fits Maidan's existing A2A surface and gets a sizing spike among the later lanes. Grok Build's plugin marketplace (PR-based, xai-org/plugin-marketplace) is a real distribution path after the maintainer's go. A quarterly re-read checks the facts the program rests on, namely each provider's plan gating, Anthropic's static request headers (a beta for a limited set of organizations), and whether Meta starts requiring per-user OAuth.

Decisions pending the maintainer

QuestionOptionsRecommendationBlocks
The launch date, the launch release, and the go for directory submissions—Cut the launch candidate once Next 23 to Next 28 and Next 30 close, and launch when the maidan-launch-1.0 gate passes on itNext 29, and the listings (Next 10, 11, 15, 16)

The maintainer delegated the rest on 2026-10-01; they are under Recently decided, and the ones that need building are in Now or Next.

External setup that blocks rows, and is not a decision: live Slack and GitHub apps for projector tests, a provider key for the Goose recipe, and Jev access for J-01.

Recently decided

Each links its record. Entries roll off after about a month.

DateDecisionRecord
2026-10-14The agent swarm's Maidan stays on a local stack (the maintainer's machine), not the hosted instances: its repositories and task content stay out of hosted storage. The hosted service (Next 24 onward) continues on its own lane, and Next 33 is built for the local stackThe maintainer, 2026-10-14; Next 33
2026-10-13The hosted service runs on Cloudflare Containers (sleeping when idle), Neon Postgres and R2, one of each per instance; an Iceberg tier on R2 takes old history laterDecisions, Next 24
2026-10-13Each workspace's message keys are wrapped by a key of its own; a cloud KMS is the next custodyDecisions, Next 25
2026-10-12The domain layout: maidan.world serves the console, the API, MCP and OAuth from one origin, docs.maidan.world the docs, dev.maidan.world the staging instance, and try.maidan.world the demoDecisions, Next 24
2026-10-12The launch is open source plus a hosted service at maidan.world, whose console takes sign-ups through a waitlist first, with invited sign-up behind itDecisions, Next 24 to Next 29
2026-10-12The hosted service is free up to an allowance of compute, storage and the like, and usage past it is billed. Metering comes before launch, billing afterDecisions, Next 27
2026-10-12The privacy policy, terms and other legal pages are the maintainer's, prepared outside the repo for launchDecisions, Next 12
2026-10-10Cut v413.0.0 once the last security PR merged, then bump the deploy pins (Next 7). No submission to any directory or registry until the maintainer says the product is ready, so the sdk-*-v0.3.0 tags waitDecisions
2026-10-09The inline approve card is an MCP Apps UI resource that decides through the host's tools/call to approval_decide, not a ChatGPT-only confirmation prompt. The deciding client is named from the credential first (a registered OAuth client), then from the client's own clientInfo shown as self-reported, then none. The confirmation link's lifetime becomes a workspace settingDecisions, Next 17
2026-10-08An approval may be decided by a model (approval_decide, a ChatGPT inline card), and acceptance becomes a property of the credential: a browser session, approval:grant, or a fresh confirmation outside the model. A token minted for an MCP client cannot accept a gateDecisions, Next 17
2026-10-08Build the OAuth authorization server at full OAuth 2.1 scope, consent in the console, public and confidential clients, no dynamic registrationDecisions, Next 23
2026-10-08Run the cost-per-success pilot on a subscription the maintainer provides, under a cap the runner enforces, publishing the cap and the varianceDecisions, Later C
2026-10-08Approval evidence carries three tiers (verified, attached, self-reported), with a warning when an approval rests on self-reported evidence onlyDecisions, #1327
2026-10-08The mark-ready live check runs on a scratch GitHub repository, not GiteaDecisions, Now
2026-10-08Maidan answers tasks/* as an unknown method rather than -32021. It does not implement the optional tasks extension, and -32021 would tell a client to declare an extension Maidan does not offer. The suite's tasks checks stay in the 2026-07-28 baseline with that reason. A review note stays out of the review_submitted event, since #1132 kept free text out of the immutable log#1302, #1304
2026-10-06Go on Meta's Connector Terms §3.1(c). The Muse lane proceeds with per-user scoped tokens, a thin tool set and a dedicated reviewer account, still shadowing the the sibling app outcomeMuse row in Next
2026-10-06A tied review reaches a human: when approvals equal change requests, the thread leaves the queue for a human instead of sitting in a tie neither side can break, and the board shows ties in a Review column#1258
2026-10-06A claim blocked by a full inbox gets a thread where the blocking worker can reach a human: the board records the block reason and note, an authenticated Unblock path exists, and the row survives a DELETE failure#1260
2026-10-06The workspace queue is one number: per-worker ceilings plus the fair-share ledger, with a MaidanWorkspaceQueueFull alert when every eligible worker is capped#1265
2026-10-06The MCP tool annotations landed: every tool carries readOnlyHint, destructiveHint and openWorldHint with a one-line reason, enforced by a contract test#1264
2026-10-06The Connect page, Capabilities, Integrations and README describe the room as it is now (workspace queue depth, claim leasing, the Inbox's Needs you)#1263
2026-10-06The board review findings closed their loop: the 15 findings are fixed on main or answered on their comments#1262
2026-10-06The Gemini CLI extension manifest is on main and stays unlisted: the gallery topic is not added until the maintainer's go, and #1319 made it reach the user's own instance#1266, #1319
2026-10-06Nothing is published or submitted to any directory, catalog or registry (Copilot included) while Maidan is being built; the Copilot listing files stay on wip/copilot-plugin#1268, Next 10
2026-10-04The review gate stays opt-in. A thread closes with no approval unless a gate is configured, and the board shows such a close as closed without reviewDecisions, Next 1
2026-10-04start_review needs a posted result on gated threads only. Elsewhere it is allowed, and the approval card warns that no result was postedDecisions, Next 1, Next 5
2026-10-04The web UI ships as a generated, minified bundle checked into the repo, kept fresh by CI, so cargo build needs no NodeDecisions, Later U
2026-10-04Nothing connected-apps is published or submitted to any directory, catalog or registry until the maintainer says go, and every submission is a version with a validation record first. Lane 9's hint and title pass moves forward as Next 14Decisions, Next 14
2026-10-04The hybrid hosting decision does not limit the hosted console. The console work in progress continues, and the strategy's service-engagement sentence is set asideDecisions, Now
2026-10-04Maintainer hours are not a constraint on the connected-apps program, so it carries no capacity number and no support-hour pause triggersDecisions
2026-10-03Connected-apps hosting is hybrid, open source first. Self-hosting is the product, a hosted demo instance serves directory reviewers (Next 12), and listing copy says plainly that production is self-hosted. Superseded on 2026-10-12: the hosted service is a launch surface, and listings name both pathsDecisions, Next 12
2026-10-03The OAuth authorization server is on hold. The connected-apps program is lanes 1 to 7 (Next 9 to Next 16). Lane 8 was parked until the 2026-10-08 decision to build it (Next 23). The Muse API-key and Claude static-headers paths are unaffectedDecisions, Later CA
2026-10-03No enterprise track until the consumer lanes measure. Lane 12 stays parked, and a real customer in one ecosystem reopens its track earlyDecisions, Later CA
2026-10-03Muse shadows a sibling app. Lane 6 waits on the the sibling app outcome with its materials prepared. A rejection of the shared API-key auth model re-scopes it to OAuth with PKCE or parks it, and a rejection on the sibling app-specific grounds changes nothingDecisions, Next 14
2026-10-03Slack replies thread by an optional thread_ts on the Slack deliver_to target, which the producer supplies; Maidan keeps no Maidan-to-Slack thread mapping for it, and the egress allowlist stays keyed by channel#1245
2026-10-03The change flow runs on David's personal PAT as MAIDAN_GITHUB_TOKEN (contents:write and pull_requests:write on the deployment repositories), so agent PRs are authored as David and nothing may depend on his approval: the flow stops at a draft PR. The shared Maidan runs in Pi's dev-tools compose stack, built from main, not PorterDecisions; #1245, #1247 and #1248
2026-10-03A token budget counts what the model processed fresh (uncached input, output, cache writes); cache reads count toward the USD budget at their price only, so caching never exhausts a token budget fasterDecisions; #1242
2026-10-03Shipped work is not still in flight: the message retention ceiling, closed vote kinds, group DMs, installing a rotated token only into the connection that asked, GitHub check runs, browser web push with a retry, MCP create_channel and create_thread, 16px controls, the palette jump, the edit pencil, first-run copy, sign-out, and the ten UI design surfaces#1232, #1231, #1230, #1229, #1228, #1225, #1226, #1219, #1224, #1220, #1179–#1196
2026-10-02Item 68 is rejected: the hero is the board, not a terminal recordingREADME
2026-10-02A schema change while two server versions share a database expands, then contracts in a later releaseMigrations
2026-10-01A production chart render refuses the dev image, default credentials and CHANGE_ME, and deploy pins keeps every deploy pin on the newest tagged release#1156
2026-10-01Every nightly job fails red; the fuzz job builds and runs every target on the gnu triple, and its first night found two real decoder bugs, fixed with regression tests (an egress URL that percent-encodes past the length limit; an MCP id that lost precision as a float, now parsed with float_roundtrip)#1160
2026-10-01#1159 and #1160 landed#1159, #1160
2026-10-01Prod renders name a release and refuse placeholders; deploy pins stay on the newest tag (#1156 landed)#1156
2026-10-01PRs merge by admin squash when the eight required checks pass on the exact head and every CodeRabbit comment is answered; no review is required while one person maintains the repoDecisions
2026-10-01Branches need not be up to date to merge (F-43 stays off); the merge loop builds each PR on current main and runs the static contracts firstDecisions
2026-10-01A squash commit carries the PR title and body, so each commit on main holds its retroDecisions
2026-10-01max_wall_secs is the thread's total worked time: every way a claim ends charges itDecisions; lane BUD
2026-10-01A member handle is unique regardless of case; existing case-only duplicates are renamed by the migrationDecisions; lane IDN
2026-10-01Artifacts are erased, never soft-deleted; the unused tombstoned_at column goesDecisions; lane IDN
2026-10-01A SCIM group records membership and grants nothing; channel access comes first if an operator asksDecisions
2026-10-01An OIDC browser session carries thread:transition, under the separation-of-duties checksDecisions; #1176
2026-10-01A token's session reaches the bearer routes except MCP, re-resolving the token's authority on every request#1142
2026-10-01Read notifications age out under MAIDAN_RETENTION_NOTIFICATIONS_DAYS, off by default; the usage ledger is kept as a billing recordDecisions; #1165
2026-10-01The SDKs publish as 0.3.0 with the next server release; 0.2.0 is skipped#1159
2026-09-30Artifact bytes are served with their stored type, nosniff and a sandboxing CSP; images render inline; no read serves a tombstoned artifact#1135
2026-09-30A blank /ui opens on a first-run card; the discovery document says which sign-in paths exist; Sign out forgets the token#1123
2026-09-30A claim freed on a lapsed lease is charged its worked time against max_wall_secs#1139
2026-09-30A verdict is a ReviewSubmitted event; a change request notifies the last worker to hold the thread#1132
2026-09-30A member id naming no member, or another workspace's, is a 404; sign-in and sign-out are audited; A2A reads are not recorded as changes#1136
2026-09-30Every audit row names a workspace (or the instance), stamped at write; a hold keeps only its own workspace's rows#1134
2026-09-30Every HTTP operation is classified as reading or changing state, and CI checks it#1121
2026-09-30A SCIM group records membership and grants nothing; a userName rename keeps the member's id#1133
2026-09-30Stateless MCP subscriptions live in a shared, expiring table, so any replica delivers them#1131
2026-09-30Retries to one host share a per-host token bucket; a refused retry is deferred, never dropped#1122
2026-09-30A SQLite backup is a VACUUM INTO snapshot; a restore deletes the old -wal and -shm#1126
2026-09-29A misspelt MAIDAN_* variable refuses boot#1107
2026-09-29A2A pushes go over https; plaintext gRPC off loopback needs an acknowledgement#1114
2026-09-29A token can be rotated: a new secret for the same authority, the old one revoked in the same transaction#1116
2026-09-29Release tags wait; they are the maintainer's call, not a per-cluster stepOperations
2026-09-29Delivery retention never prunes a pending row or a dead letter#1108
2026-09-29Every egress request times out (5 s to connect, 10 s in all); an A2A task holds at most 10 push configs#1109
2026-09-29A WebSocket subscription announces only its own member#1112
2026-09-28Withdrawn messages are crypto-shredded; the server refuses to start without a KEK#1063, #1064
2026-09-25A change request reopens the thread and dismisses approvals#1054
2026-09-25A legal hold keeps withdrawn words; holds are per matter#1056, #1057
2026-09-23D-A: authority changes write their audit row in the same transactionDecisions
2026-09-23D-B: a per-workspace grant ceiling, 90 days by defaultDecisions
2026-09-23D-C: delegated capabilities are a two-way intersection; members carry noneDecisions
2026-09-23Approvals may be borrowed, never self-approvedDecisions
2026-09-23F-54: no /v1 and no compatibility promise before 1.0Decisions

Known risks

RiskMitigationResidualWatched by
An agent holding a person's token accepts an approval gateAccepting needs a browser session the person signed in to, sent from the console page, or a token holding approval:grant, and nobody accepts their own request (with auth on, since AUTH_DISABLED checks no identity) (#1280, #1325). A plain bearer, a delegate token or a session made from one can only decline or cancelA token a person mints with approval:grant and hands to an agent still accepts. maidan init's admin token holds it. A model asking through approval_decide (#1332) gets a confirmation link a person spends in the console, unless the token holds approval:grant and the gate is below the workspace threshold (by default none is)Next 17
A pasted bearer token lives in localStorageTokens are capability-scoped, revocable and rotatable (#1116); #1093 escapes the page's innerHTML writes; #1142 exchanges the token for an HttpOnly session; /ui sends a Content-Security-Policy (#1213)A script injected into the page can act as the session while the page is open but cannot take the credential away (Threat-Model T17)#1142, #1213
Admin merges while branch protection is not strict (F-43, kept off on 2026-10-01)The merge loop reads the checks of the PR's exact head commit, requires all eight required checks there and every CodeRabbit comment answered, merges with --match-head-commit, and first builds the PR merged onto current main and runs the static contractsA break that only a full test run on the merged tree would catch; main's own CI catches it after the mergemain CI; Process below
Events delivered at most once on the optimistic pathTransactional outbox, quarantine and replay; opt-in at_least_once delivery per consumer_idA client that does not opt in can see a gap or a duplicatemaidan_outbox_quarantined, MaidanOutboxQuarantined
AUTH_DISABLED or bootstrap left onBoth refuse boot without an explicit acknowledgement, and always in production; hardened builds strip the pathA dev binary exposed to a networkBoot checks
The embedding indexer falls behindRetries, a repair sweep, and /health/ready degraded past INDEXER_STALE_SECSINDEXER_STALE_SECS is off by defaultmaidan_indexer_last_event_age_seconds
hash-v1 embeddings are not semanticA boot warning; openai-compatible for real useA deployment that ignores the warningBoot log
The Postgres bus listener dropsReconnect with back-fill from the logDelay while it reconnects/health/ready, maidan_bus_lag_total
RUSTSEC-2023-0071 (rsa)Ignored with a reason; RS256 verification onlyClears with openidconnect 5cargo-deny
Review findings merged unreadSince 2026-10-01 the merge loop holds a PR while any CodeRabbit comment is unanswered126 comments on PRs merged 2026-09-28 to 2026-10-01 were never answered (20 marked major). The triage (2026-10-01) found 75 valid, 43 not applicable and 8 fixed on main, and answered the 51 that need no change. Lanes SEC and CRD fixed the 59 outside index.html (#1167, #1168, #1183, #1186, #1189, #1191 and #1162); the index.html items rode with the review-findings row and closed in #1262. Threads on #1260, #1262 and #1263 merged unreplied through the API; a retroactive audit answered each one on 2026-10-06the merge loop
One tenant saturates a shared instancePer-token and per-workspace rate limits, the in-flight ceiling, statement and lock timeouts, egress timeoutsNo CPU or IO isolation between tenantsmaidan_http_shed_total, MaidanLoadShedding

Won't do

ItemWhyRecord
Re-recording docs/assets/handoff-demo.gif (item 68)The hero is the board, not a terminal recording2026-10-02
Postgres row-level securityIsolation is enforced in the application and proven per route by tenant_isolation_e2eDecisions (v216.0.0)
A workflow engine (Restate, Temporal)The outbox, DAG and scheduler already give the semanticsDecisions
MCP argument defaulting (author_id from the caller); hoisting the context assembler into maidan-routerA semantic change to the post path for little gain (whoami covers self-discovery); multi-crate surgery when the shared fold already lives in maidan_typesCluster 349 (archive)
The flagship arc's optional tailDeclined at v331.0.0Decisions
F-48 Tier 3, F-53, F-33, J-06Declined on the meritsarchive
Batched pg_notify; the ACP IDE bridge; multi-region active-active; a CRDT logOut of scopeRoadmap
The A2A TCK's scenario groupsThey need a scripted agent, which Maidan is notscripts/a2a-tck/exclusions.txt
Wildcard egress selectors; MCP twins of the egress allowlistAn allowlist must name ids, so a wildcard defeats it; the result-delivery allowlist is operator policy, set over REST by token:admin (the per-workspace secret-egress allowlist in #1140 is a separate list with MCP tools)Result Delivery
J3's request_clientAn optional MCP 2026-07-28 feature no client relies onRetro 303
Retroactively tagging v411.0.0It would rewrite a recorded history; the record says "never tagged"Thread 22, #1078
Emoji as verdictsA reaction is not a decision; cast_vote already refuses emoji kinds, and a verdict must carry its whyUI deep dive 2026-10-03 (R3, R5)
Bulk approve or bulk closeA rubber-stamp accelerant: each approval binds its own evidence and state versionUI deep dive 2026-10-03 (R3, R5)
Agent trust scoringA score invites approving the agent, not the workUI deep dive 2026-10-03 (R3, R5)
A graph debugger at the approval surfaceThe approval card shows the evidence bound to the decision, not orchestration internalsUI deep dive 2026-10-03 (R3, R5)
Fleet chromeAttention goes to what waits on a human, not to a dashboard of agentsUI deep dive 2026-10-03 (R3, R5)
Read receiptsSurveillance signal with no supervision valueUI deep dive 2026-10-03 (R3, R5)
Role theatrics (agent personas, titles, avatars as roles)Capability and status are the real model; costumes obscure itUI deep dive 2026-10-03 (R3, R5)
Huddles and voiceOut of scope for an agent work roomUI deep dive 2026-10-03 (R3, R5)
Skill publish-back from agentsA prompt-injection vector into every consumer of the skillUI deep dive 2026-10-03 (R3, R5)
A crew-builder galleryTemplate theater; agents connect through MCP, A2A and the SDKsUI deep dive 2026-10-03 (R3, R5)
Auto-proceed on human timeoutDecided: a timeout returns the work to the queue, never proceedsUI deep dive 2026-10-03; P2 human-timeout row
A PulseMCP submissionSubmissions are paused (the notice is dated September 3, 2026, and still holds on 2026-10-04)Connected-apps strategy, 2026-10-03
Zed MCP server extensionsZed is deprecating them in favour of the official registry, which Next 11 coversConnected-apps strategy, 2026-10-03
A GPT Store presenceCustom GPTs retire on December 11, 2026, and plugins are the migration pathConnected-apps strategy, 2026-10-03
An Alexa+ integrationPartnership only, in an unrelated verticalConnected-apps strategy, 2026-10-03
An Amazon Q Business directory playNo directory exists, only per-tenant custom pluginsConnected-apps strategy, 2026-10-03
A WhatsApp Business Agent listingNo listing surface existsConnected-apps strategy, 2026-10-03
The mcp.so paid tier and the mcpmarket.com paid submissionPaying for a listing buys little next to the free catalogs in Next 11Connected-apps strategy, 2026-10-03
A Windsurf-specific pathNo public submission path exists, and Open VSX reaches its usersConnected-apps strategy, 2026-10-03
Listings on package managers, LLM gateways, integration platforms, agent frameworks and sandboxesNone of them takes third-party MCP server submissionsConnected-apps strategy, 2026-10-03
Automating logins to personal ChatGPT or Claude accounts for testsAn account-risk decision, not a test-engineering one, and it would need its own reviewDev and test methodology v2, 2026-10-06
A plain-text "reply APPROVE" approvalA free-text approval can be injected by tool output or pasted contentDev and test methodology v2, 2026-10-06
Testing a Grok chat-app installNo such surface exists. The Grok API and Grok Build CLI are the testable pathsDev and test methodology v2, 2026-10-06
Automating the Muse clientMeta publishes no API for driving the assistant, so Muse is tested by manual walkthroughDev and test methodology v2, 2026-10-06
A backend fork per provider for the board, inbox or approvalsOne tool result feeds every rendererDev and test methodology v2, 2026-10-06
Asserting byte-identical replays from LLM-driven clientsTheir tool sequences are not deterministic. Recorded traces are reviewed by a person insteadDev and test methodology v2, 2026-10-06
Recording live OAuth token endpoints in cassettesA fake authorization server double covers them without capturing secretsDev and test methodology v2, 2026-10-06
Listing through OpenAI's enterprise marketplaceIt is a procurement and billing channel with named launch partners, not a self-serve directoryProvider research v1, 2026-10-06
Treating Gemini's skills (formerly Gems) as a distribution surfaceThey carry instructions only, with no tool binding and no sharing at launchProvider research v1, 2026-10-06

Process

Merge discipline while branch protection is not strict (thread 43). A PR merges when every one of the eight required checks has passed on its exact head commit and nothing else on that commit is queued, running or failed; the merge names that commit (gh pr merge --match-head-commit), so a push in between makes GitHub refuse it. Before merging, the PR is merged onto current main locally and built, and the static contracts run on the result (attribution_scope_contract, authority_audit_contract, http_operation_kinds_contract, docs_numbers_contract, env_registry_contract, ui_js_contract, openapi_well_formed, the event-kind and lexicon contracts, migration_register, backend_parity). Stacked branches rebase in dependency order, replaying only their own commits. Two merges broke this on 2026-09-30 and are why the rules read as they do: #1124 merged while gh pr checks still showed the previous commit's runs, and #1133's last commit merged two seconds after a push, before GitHub reported the new head. main's CI passed on #1124's merge; #1133's is recorded in its PR.

Open Work is the coordinator's. Feature PRs do not edit this file or the Roadmap; the coordinator reconciles them after merges, and the open work job runs on main and on PRs that edit the file. The merge loop's pre-merge build takes a lock that names its holder, and a lock whose holder is gone is taken over: a killed loop once held every merge for five hours (2026-09-30).

Review comments. CodeRabbit reviews every PR (Decisions). Each top-level comment is fixed, or answered with the reason it does not apply, before the merge; the merge loop holds a PR while one has neither a reply nor CodeRabbit's "Addressed in commit" marker. From 2026-09-28 to 2026-10-01 the loops merged without that check, which is how 126 comments went unanswered (75 of them valid, one a cross-tenant rate-limit bug).

Old branches. A branch whose work shipped another way, or was closed, is kept as an archive/<branch> tag and then deleted (the six cursor/* branches, 2026-10-01). Stashes are not left on the shared stack: they are kept as local refs/archive/stash/* refs, which are never pushed because a stash can hold untracked files.

UI changes (thread 42, 46). The PR template's /ui checklist is run by hand before a UI PR is opened: the token path and the OIDC path, keyboard only, a 390 px viewport, and every new string re-read.

Enhancement thread 2026-09-30: dispositions

The 2026-09-30 entries (28–57) and the supersessions of 27, 28, 29 and 35. Entries marked done on main since the thread's 1e612cf8 snapshot are noted.

ThreadItemDispositionWhere
28CSP for /uiDone in #1213: /ui sends the supersession header#1213
29Write paths for session usersDone in #1176: an OIDC session can edit, upload, and paste, the four proxies exist, and the session carries thread:transition#1176
30Hover-only controls, 16 px inputsDone: the pin toggle reveals on :focus-within, and inputs, selects, and textareas are 16pxCHANGELOG
31Palette jump leaves the sidebar on the old channelDone in #1224: selectThread selects that channel and its sidebar row#1224
32First-run copyDone in #1224: the card says a workspace id is the id of one room on this server, and that maidan init prints it#1224
33Message click affordanceDone in #1224: a pencil and a click open Edit message#1224
34TCK numbers disagreeAdopt: the two sets come from two checks (the TCK's pytest summary and the walkthrough), and the comment conflated themLane U
35MCP has no create-thread toolDone in #1226: create_thread and create_channel, both workspace:write#1226
36llms.txt says an unleased claim never lapsesDone in #1149: llms.txt says every claim is leased, 600 s by default, and a lapse returns the task#1149
37Enums on string inputsDone: transition_thread.action is start_review, close, or archive (#1201); set_delivery_mode.mode is immediate or digest; cast_vote.kind is approve, request_changes, or ack (#1231)#1201, #1231
38Wait families look alikeAdopt, as see-also sentencesLane U
39DM and group-DM duplicationDone in #1207: DM and group-DM message loads share one function#1207
40One fetch wrapper and one feedback surfaceDone in #1207: calls go through api(). showError and setStatus stay separate#1207
41A checked API client for the UIDone in #1207: scripts/gen-ui-client.mjs regenerates the typed path catalog. tsc does not run in CI#1207
42Dead CSS and a lintAdapt: .chrome-idle and .brand-sub are gone (#1224). A lint for dead CSS is not in CINext, review findings
43F-43 and merge orderAdopt the discipline, which is written in Process; strict stays off (decided 2026-10-01); the "fail any PR whose merge-base is older than 24 h" CI rule is rejected, because it would rerun every open PR's full CI after each merge on a runner pool that is already the bottleneck, and the pre-merge build on current main catches the same breaksProcess; Decisions pending
44Open Work as a CI contractAdapt: scripts/check-open-work.sh fails when a PR under Now has merged or the stamp is not on main; a per-row check: line is deferred until the table is stable enough to be worth scriptingThis file; CI open work
45thread:transition for browser sessions; one owner for the browser-authority chainDone in #1176. An OIDC session carries thread:transition, under the separation-of-duties checks; the chain is warn (#1123), rotate (#1127), exchange (#1142, which also drops csrf_secret), with one owner (the coordinating agent); on rotation the session ends and the page exchanges the successor, rather than migrating the session row#1176
46data-ui-version never versionsDone in #1224: the marker and the assertions that required it are removed#1224
47The money shotsDefer: the ten design surfaces are on main (#1179–#1196); no board screenshot exists yet, and the terminal GIF stays (item 68)Next, the money shots
48UI improvement specsDone: the ten surfaces landed (#1179, #1181, #1182, #1185, #1187, #1188, #1190, #1192, #1193, #1196). The screenshot bar is Next, the money shots#1179–#1196
49Split as TypeScript from the startDone in #1207 as ES modules with JSDoc. tsc --noEmit --checkJs does not run in CI#1207
50Playwright and unit gapsAdopt: specs for prefs, slash commands, delivery replay, token mint and revoke, and DMs landed in #1205. A group-DM spec posts in the conversation it opens (#1230). helpers.test.mjs does not run in CINext, Playwright and unit coverage
51SaaS-agnostic hygieneAdopt: per-workspace fairness by default and per-workspace retention; the migration policy is expand, then a later contractFairness and retention shipped (#1153). The policy is Migrations
52Do not build a hosted service yetAdopt as recordedLater, L
53Stale token error after a successAdoptNext, UI fixes from the QA pass
54A failed post is lost silentlyAdoptNext, UI fixes from the QA pass
55Channel refresh shows TypeErrorAdoptNext, UI fixes from the QA pass
56No sign-out for a token userDone in #1123: Sign out is offered to a token and forgets it#1123
57Opening a DM does not select itDone: a one-to-one DM selects (#1157); a group DM selects and asks for three members (#1230)#1157, #1230
27 → 49Module splitSee 49#1207
28 (superseded)CSP header and sequencingSee 28#1213
29 (superseded)The 19-site tableSee 29#1176
35 (superseded)MCP create_thread and create_channelSee 35#1226

Done since 1e612cf8, per the thread's own list: 3 (#1118), 13, 14a, 19, 20, 22, 23 (#1113; 23's numbers corrected by lane U). The 2026-09-29 dispositions below stand, except where a row above supersedes them.

Enhancement thread 2026-09-29: dispositions

David's auditor re-verified each item five times against main and freshened it to 70a6d78b. Each item's disposition, and where it lives now. Items 5, 21 and 25 were struck by the thread itself (false premises) and are not re-filed.

ThreadItemDispositionWhere
1Inline errors instead of alert()Adopt, P0Done, #1117
2aWarn that the token is stored; surface rotationAdopt, P0#1123, #1127
2bhttpOnly cookie sessions for the UIAdapt: the session cookie already exists and is HttpOnly; SameSite=Lax (session/mod.rs). The work is exchanging a pasted bearer for it, and verifying or removing the unread csrf_secret#1142
3One primary thread surfaceAdopt, P0Done, #1118
4Inline attachment previewsAdopt, with nosniff and a sandboxing CSP on artifact bytes#1135
6Header cleanupAdapt: the residual after #1086's Connect sheet#1123
7Edit affordance on messagesAdoptNext, UI fixes from the QA pass
8Reorganize the tools drawerAdapt: the palette (#1086) is the fast path; group the tabs and drop the Work tab's copy of the boardNext, the /ui design contract
9Dead #live-* CSSAdapt: the first block is not dead (see below); merge the two into one rule per element insteadDone, #1117
10Per-peer egress allowlistDefer until a real federation peer; production already refuses the bypassLater, Federation
11Token rotation endpointAdopt, with 2aDone, #1116
12Board screenshot in the READMEAdopt, after the P0s so the image shows the fixed UI, captured by a scriptNext, the money shots
13The recording, diagram and session in the docs siteAdoptDone, #1113
14aCluster 413 overstates the D-A guaranteeAdoptDone, #1113
14bMake the D-A guarantee tighterAdapt: widen authority_audit_contract to every crate with the two carve-outs named; pinning, not a holeLater, S
15gRPC TLS by defaultAdapt: refuse plaintext off loopback without an acknowledgement now; native TLS laterDone, #1114; Later, R
16A2A push accepts httpAdoptDone, #1114
17Board render for large listsDefer: measure firstMeasure before scheduling
18catch_up pagination at scaleDefer: it is keyset-paginated with a limit, so flat by construction; measure before changingMeasure before scheduling
19README says 165 toolsAdopt, with a contract testDone, #1113
20Conformance jobs required, or a drift policyAdapt: the drift policy is written (Conventions); promotion is the maintainer'sDone, #1113
22Release checklist step for taggingAdapt: tag the day the record merges or relabel it never-tagged; no retroactive tagDone, #1113
23Record the TCK run summaryAdoptDone, #1113
24First-run onboardingAdapt: the residual after #1086#1123
26Narrow-viewport and keyboard QAAdapt: #1093 landed; its residue is the keyboard and 390 px pass in the UI specsNext, the /ui design contract
27Split static/index.htmlAdopt, after the P0s; superseded by 49#1207

Sequencing, as it ran. The P0s went first: inline errors (#1117) and one thread surface (#1118) merged on 2026-09-30, and the token chain is #1116 (merged), #1123, #1127 and #1142.

Where the thread was wrong. Item 2b assumed the UI had no cookie session: crates/maidan-server/src/session/mod.rs already issues HttpOnly; SameSite=Lax (and Secure when configured) cookies for OIDC sign-in, and each session stores a csrf_secret that no handler reads, so SameSite=Lax is the CSRF defence in force. Item 9 took the first #live-panel / #live-toolbar / #live-feed block for dead because a later block restyles the same elements, but the cascade is per property: the later block never sets the flex layout or the feed's colours, font, overflow and wrapping, so removing the first would break the Live bar. Everything else checked out.