Concurrens
SaaS git with bespoke CI/CD and environment management that support my other projects. Plus work and project management on-demand.
Concurrens
An event-sourced engine for resource-aware work management.
This is the distribution repository: it composes the editions from the published primitives. For working across the repositories, see the multi-repo workflow.
Concurrens unifies plan, track, commit on one shared resource pool, so scarce, interdependent resources are never double-booked across an organisation. At its center is a no-double-book reservation core: every booking is a version-guarded, multi-stream transaction over a single Postgres event store, enforced in the database rather than by replaying history, above projects and across a tenantβs whole catalogue. Around that core sit order-free surfaces a project mixes freely: a typed booking catalogue, a live board (kanban with a workflow state machine and WIP limits, grown into a Jira-class work tracker: human-readable item keys, comments with @mentions and reactions, labels, first-class priority, an item-type/subtask/epic hierarchy, typed and custom links, watchers, votes, and attachments, plus the agile substrate β a typed CQL query language with saved filters, sprints/backlog/velocity, status categories + resolution, nine fold-only report models, dashboards, versions, worklogs, and a pack-configured automation engine), and a real-time collaborative canvas (co-edited through a single-authority op sequencer, with optimistic local apply and byte-identical convergence), plus a live read-side that streams committed events to every subscribed client. The same engine also runs a developer code forge (git hosting, container CI, merge-request review, and deploy environments) on the identical event-sourced spine. A vertical (events/production, makerspaces, studios) is a declarative pack (resource types, workflow states, booking policies, RBAC roles, terminology), not a fork; one instance runs many tenants and domains.
Architecture
Concurrens is a layered, event-sourced platform. A dependency-free kernel (domain vocabulary, the expression/CQL/duration languages, the collaboration wire protocol) underpins a platform of reusable, surface-agnostic substrates β the Postgres event store, identity + RBAC, the pack runtime, live transport, the generic search/notification/outbox hosts, and the code-forge substrates β over which sit order-free surfaces a project composes freely: booking, board, canvas, the work-OS, and the code forge. Each layer depends only downward, and capabilities are selected per edition (a locked capability set) so an installation ships exactly what it uses.
At runtime the selected capabilities compose into one modular JVM over one Postgres event store by default β one deployable, one system of record, atomic cross-cutting changes. Modules are drawn along concern seams, each owning exactly one concern, so the deployment shape is an open choice: a capability can run as its own service when a workload calls for it.
| Layer | Responsibility |
|---|---|
Core (kernel Β· es-core Β· identity Β· tenancy-rbac) | System of record + identity: the Postgres event store (single source of truth, version-guarded transactional append, async checkpointed projections, replay + point-in-time), domain primitives, tenant/project provisioning, and the JWT + RBAC command-boundary guard |
Platform capabilities (pack-engine Β· live-transport Β· collab-protocol Β· process-managers Β· collab-sequencer Β· scheduler Β· object-store Β· secrets-vault Β· outbox Β· notification) | Surface-agnostic substrates: declarative pack loading/validation + the typed rules-DSL evaluator/host (the policy escape hatch), the in-memory WebSocket fan-out hub + presence behind an EventFeed port, the byte-locked language-agnostic wire protocol, event-driven cross-surface sagas (pack-configured, exactly-once), durable replay-safe timers, off-log blob + secret side-stores that keep only a reference-by-ID on the event log, the integration outbox (log-as-outbox, HMAC-signed webhooks) + per-principal live notifications, and the code-forge substrates (git-store: bare JGit repos as an off-log side-store with smart-HTTP and SSH push/pull (key/deploy-key/deploy-token auth) + a RefUpdated change-feed, protected branches/tags + push policy behind one ref-write gate, repo lifecycle with redirects, web file editing, reads depth (blame, per-path history, permalinks, archive/raw/patch), releases + Git LFS, commit-signature verification, and code content search; crate-registry: a cargo sparse registry whose index folds from publish events; ci-orchestrator + the external ci-runner: event-sourced container CI over a needs-DAG; forge: the merge-request/review aggregate with a real in-core merge and required-green) |
Surfaces (booking Β· board Β· canvas Β· the work-OS checkin/requests/recruiting Β· the forge code/ci/environments) | The user-facing verticals: each a pure-data contract + a domain Decider over the shared core. Order-free, a project uses any subset |
Client (app shell Β· booking-ui Β· board-ui Β· ui-kit Β· client-core Β· sync-client) | A unified Vite React shell that mounts each enabled surface from GET /client-config, a shared ui-kit design system (tokens + light/dark theming + components), the REST client typed from the served OpenAPI contract, and the framework-free live client |
ββ BROWSER β TypeScript app shell (Vite) βββββββββββββββββββββββββββββββββββββββ
β surfaces: booking-ui Β· board-ui Β· canvas-surface β
β checkin-ui Β· requests-ui Β· recruiting-ui Β· insights-ui (M9) β
β code-ui (repo browse Β· diff render (M11) Β· MR review (M13)) β
β ci-ui (pipeline list Β· DAG Β· live job logs) (M12) β
β environments-ui (env list Β· spec YAML Β· up/down Β· deploy) (M14) β
β sync-client (live read fan-out + presence) Β· client-core (typed REST) β
β collab-client (optimistic co-edit) Β· canvas-renderer (Rust/Wasm, no auth) β
βββββ¬βββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β HTTPS / REST (Tapir API: β WebSocket /live:
β commands + reads) β read fan-out + per-room op ordering
βΌ βΌ
ββ SERVER β Scala modular JVM (one always-on node) βββββββββββββββββββββββββββββ
β http4s / Tapir API Β· JWT + RBAC tenant guard Β· GET /client-config β
β surface command handlers: booking Β· board Β· canvas Β· checkin (M9) β
β board = work-OS tracker: keys/comments/rank (M17) Β· org/links (M18) β
β es-core (append + project + replay; single system of record) β
β live-transport (WS hub + presence) Β· pack-engine (config Β· rules-DSL) β
β process-managers (sagas) Β· collab-sequencer (single-node Pekko op ordering)β
β scheduler Β· object-store Β· secrets-vault Β· search Β· saga-registry (M6) β
β outbox (log-as-outbox Β· HMAC webhooks) Β· notification (per-principal) (M7) β
β insights (config-parameterized read-models) Β· membership (M9) β
β identity (Principal aggregate Β· sessions Β· SCIM + PAT) Β· audit β SIEM (M10) β
β git-store (bare JGit Β· smart HTTP Β· RefUpdated + reconciler Β· groups) β
β crate-registry (cargo sparse index Β· inline-fold RYW Β· yank) (M11) β
β ci-orchestrator (pipelines Β· DAG advancer Β· job queue Β· logs/artifacts) (M12) β
β forge (merge requests Β· review Β· in-core merge Β· required-green) (M13) β
β environments (env aggregate Β· publisher Β· per-env-host serving Β· deploys) (M14)β
β β
ci-runner (external binary: claims jobs, runs docker containers) (M12) β
ββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββ
β append / read (one event store)
βΌ
ββββββββββββββββββββββββββββββββ
β Postgres - event store + β
β projection read models β
ββββββββββββββββββββββββββββββββ
Why this shape.
- Event sourcing is the core, not a feature. Durable, replayable state is intrinsic (replay = recovery): the write side is forced to handle transactions, auth, and multi-tenancy at commit time, and the read side folds the one log into projections. There is a single source of truth in one process, not two append-only logs to reconcile.
- One modular JVM, by choice. The concern seams are real β each module owns one concern, and collaboration depends only on
kernelβ so the selected capabilities compose into a single process over a single event store: atomic cross-cutting changes, one system of record. Those same seams keep the deployment shape optional: a capability can run as its own service when a workload calls for it, so monolith-or-services is an open choice. - Server-authoritative, thin client. The event store is the single authority; the client holds only optimistic state reconciled against the server, plus a Rust/Wasm canvas renderer with no authority (it only draws what
collab-clientfolds). This is deliberately the opposite of a compute-offload split. - One always-on node, cost-gated. The core (booking + board) scales to zero with no idle burn, and the canvasβs per-room sequencer rehydrates from the log on wake, so it too survives scale-to-zero; only β₯2-warm-node cluster sharding (a later, burn-gated milestone) forces a standing warm node. Live-running cost is therefore gated on operational burn, not on build effort: capability is built to full throughout, and only the runway-burning slice waits.
Tech stack
- Server: Scala 3 Β· Cats Effect 3 Β· http4s Β· Tapir (contract-first / OpenAPI) Β· Doobie Β· Flyway Β· circe Β· jwt-scala Β· Apache Pekko (typed actors: the single-node
collab-sequencerroom-per-canvas op ordering, bridged to Cats Effect) Β· Google Tink (envelope encryption forsecrets-vault) Β· AWS SDK v2 (S3-compatibleobject-store, presigned direct-to-store upload) Β· Eclipse JGit (git-store: bare repos, smart-HTTP UploadPack/ReceivePack, structured reads, in-core merges) Β· docker CLI (the externalci-runnerβs per-job container execution) Β· Apache Commons Compress (environments: artifact untar behind the publish trust boundary) Β· Bouncy Castle BLAKE3 (Cloudflare Pages asset hashing) - Store: Postgres (event store + projection read models, JSONB payloads; Postgres full-text search for the cross-surface
searchindex) Β· an S3-compatible object store for off-log blobs (Cloudflare R2 in production, MinIO locally) - Client: TypeScript Β·
openapi-typescript(client typed from the served contract) Β· React surfaces (booking-uiΒ·board-uiΒ·canvas-surfaceΒ·code-ui) in a unified Vite app shell Β· a sharedui-kitdesign system (design tokens + light/dark theming) Β· dnd-kit (board drag) Β· a framework-free WebSocketsync-client+ optimisticcollab-client - Renderer: Rust β WebAssembly (
wasm-pack, Canvas2D viaweb-sys): the authority-free canvas renderer (render-scene + viewport culling + spatial-index hit-test) behind a narrow JSβWasm boundary - Build / CI: sbt (multi-module) Β· pnpm workspaces Β· Cargo +
wasm-packΒ· GitHub Actions Β· Docker Compose (containerised toolchains + the one-file self-managed deploy stack,deploy/)
Roadmap
Each milestone is loadable and reviewable before the next begins.
| Milestone | Capability | Status |
|---|---|---|
| M0 - Substrate skeleton | Event store, provisioning, auth + RBAC, pack loader, typed API + client; the structural gates green | β Done |
| M1 - Booking vertical | Typed resource catalogue (serialized + bulk), kits, no-double-book reservations over an interdependent resource graph enforced by a full-scale exclusion/capacity guard, all five policies, place/cancel/reschedule lifecycle, availability read-model | β Done |
| M2 - Live read-side | Server-ordered fan-out of committed events over WebSocket (subscription + presence + reconnect/catch-up) driven by a LISTEN/NOTIFY event-log feed; the first rendered, hands-on React UI with a live availability view | β Done |
| M3 - Board surface | A live kanban: work-items, a workflow state machine, WIP limits, strict typed card fields, event-level resolution, live fan-out + presence; plus a unified, config-selectable app shell mounting each surface from GET /client-config | β Done |
| M4 - Configurability proof | A module catalogue (every surface or capability config-selected through one seam), process-managers event-driven cross-surface sagas (pack-configured, exactly-once, forward-recovery), and a live pack-swap to a second vertical (makerspace) with zero engine-code change | β Done |
| M5 - Canvas surface | A real-time collaborative canvas: a single-node Pekko collab-sequencer (write-side op ordering, sole-writer per room), optimistic-apply collab-client (property-LWW + delete-wins tombstone, byte-identical convergence), a Rust/Wasm renderer (authority-free, 10k-culled), registered as an entitled βProβ surface; the collab-protocol Β§10 conformance suite; and the canonical PlanApproved saga driven off a real canvas with a saga-owned per-object reserved/rejected/pending overlay | β Done |
| M6 - Platform capability substrates | Four surface-agnostic substrates, each with one real consumer, selected by pack config: scheduler (durable replay-safe timers, version-0 fire-once, one-shot + recurring), object-store + secrets-vault (off-log side-stores, reference-by-ID: presigned direct-to-store blobs, envelope-encrypted secrets with rotate/erase), and cross-surface search (RBAC-filtered Postgres-FTS projection); plus the process-managers saga-registry and the first client-feature path (global search box + canvas upload control) | β Done |
| M7 - Integrations & automation | Committed events flow outward as HMAC-signed webhooks (outbox = a checkpointed dispatcher over the log itself, at-least-once with retry/dead-letter, the signing secret in the vault - its first live consumer) and inward as live in-app alerts (notification = an outbox consumer with built-in typed producers β per-principal streams, delivered live over a new owner-match Notifications channel, rendered as the app-shell bell); both pack-selected capabilities, plus a minimal webhook-management admin UI | β Done |
| M8 - Rules-DSL / plugin host | A typed, total, data-encoded expression evaluator + named-function registry - the pack-engine policy escape hatch (pure evaluator factored to kernel, JSON codec + compile + registry + rules slice host in pack-engine): wired live into bookingβs policy chain (computed-threshold reject + conditional cert-gate), with the saga when-guard built + synthetic-tested for M9; typecheck-at-load, total/sandboxed, config-as-data | β Done |
| M9 - Work-OS vertical (B2 capstone) | A third vertical (internal-ops), structurally unlike the first two, on the same engine with zero engine change: checkin/requests/recruiting surfaces + per-transition permissions; the M8 saga when-guard flipped live (auto-approve leave when fields.days <= 2) via a permission-checked service-role move; people-as-resources (an approved leave reserves the person; an overlapping second is rejected by the M1 engine + notified live); project membership + resolver-based notifications; contract-level work-item links (DAG-checked β Gantt); FieldType.Blob attachments; computed booking buffers; and a config-parameterized insights module (leaderboard/dashboard/Gantt/attendance) behind four Surface entries | β Done |
| M10 - Enterprise & Trust (B5) | The enterprise auth ladder as an auth config slice over built-in mechanisms, gated by enterprise.* grants, IdP secrets by credentialRef to the vault. Phase 1 (identity foundation): a first-class event-sourced Principal aggregate replacing the seed map, an Argon2id off-log credential store, and session management (short-TTL access tokens + refresh + revoke-at-refresh). Phase 2 (enterprise gates): OIDC + Google SSO (JWKS/RS256 verified only at the callback), TOTP 2FA (enroll/challenge/recovery-codes), and SAML 2.0 SP (Santuario XML-signature, SP-initiated POST binding, pinned IdP cert) - all federated logins resolving to the one Principal via a single claimβPrincipal seam, provider instances a runtime auth-provider stream. Phase 3 (SCIM + audit + actor seam): the additive actor-in-metadata dispatch stamp single-sourced at the secured choke-point, an audit-export projection folding the log to a SIEM sink, and SCIM 2.0 provisioning (Users + Groups) on a tenant-scoped PAT that maps onto the same Principal aggregate - a deprovision revokes every session and self-audits, all gated by enterprise.* + the client admin/session surfaces | β Done |
| M11 - Code hosting (B8, first third) | Git hosting + a cargo registry on the same substrate, run against the operatorβs own repos (retiring a private Gitea): bare JGit repos as an off-log side-store with smart-HTTP push/pull over PAT auth, a RefUpdated change-feed + reconciler (a push never fails after refs move), a product-wide nestable group namespace, a structured browse API + code surface, and a cargo sparse registry with inline-fold read-your-writes - proven by a real cargo publish + downstream cargo build against compose | β Done |
| M12 - Container CI/CD (B8, second third) | A real CI system on the same log: event-sourced pipelines/jobs created from a .concurrens-ci.yml parsed at the pushed sha (invalid files visibly so), advanced by a checkpointed decider-law consumer (needs-DAG + stages sugar, fail cascade, never-green-on-cancel verdicts, retry with resurrect), executed by an external ci-runner binary claiming work via version-guarded appends and running each job in a docker container (sibling containers, short-lived clone tokens, per-job timeouts, dead-runner reaping); live log tails + archived logs and per-path artifacts in the object store, vault-backed CI variables masked at the wire, manual jobs + manual triggers, and the ci-ui pipeline/DAG/logs surface | β Done |
| M13 - Merge requests & review (B8 complete) | The review lifecycle as an ordinary event-sourced aggregate: MRs with three-dot server-structured diffs, sha-anchored comment threads (outdated-at-read on head moves), approvals with requiredApprovals policy + no self-approval, notifications and cross-surface search; a real in-core JGit merge behind a ref CAS (conflict 409 with paths, race loser 409s, crash-window heal, replay-intact); decider-enforced required-green off a reactor stamping M12 pipeline verdicts onto the MR stream; MRβwork-item links riding the board contract; and the flagship M13AcceptanceSuite walking push β review β red-blocks β green β merge on the one log | β Done |
| M14 - Deployment environments | The forgeβs deployment story: user-keyed event-sourced environments with a declarative UI/YAML-round-tripped spec (closed schema, byte-stable canonical emitter), a checkpointed publisher resolving latest-green CI artifacts into content-addressed blobs (streaming untar behind a trust boundary, exactly-once replay, retention + orphan-GC), per-env-subdomain serving origin-isolated from the forge and each other (wasm MIME, per-prefix COOP/COEP, ETag, per-mount SPA fallback), a provider-agnostic DeployTarget port with a Cloudflare Pages Direct Upload impl (wrangler-faithful blake3 hashing, _headers synthesis, domains strictly provider-side), vault-backed per-env secrets, the environments-ui surface - plus the self-managed one-file compose (deploy/: engine + postgres + minio, opt-in TLS/runner/seed profiles, Tink KEK minting) | β Done |
| M15 - Self-managed editions | The edition build system: a declarative capability-set manifest compiles each edition (events-production full + starter, makerspace, workos, forge, dev-all) into a focused artifact that provably lacks excluded capabilities - per-capability wiring-unit sbt projects + a codegenβd typed EditionWiring (excluded modules off the classpath), one pruned pack baked at PACK_PATH, physically-pruned client bundles with an in-build canary scan, a first-admin bootstrap (env credentials or a race-safe claim wizard - no demo users in customer artifacts, structurally), per-edition GHCR images with build-info.json baked, and self-contained deployment bundles (dist/editions/<e>/: tag-pinned compose, in-bundle seeds, generated runbook, image-pinned fly.toml) proven zeroβrunning on a cold machine | β Done (engine + build system; the public demo deployments are operational tasks tracked in the plan) |
| M16 - Forge UI parity + micro-FE emission + onboarding | GitLab-level forge screens over the existing commands/projections (repo create/browse/settings with read-only archive + HEAD-relinked default branch, MR review depth with authors/name-directory/cross-repo lists + anchor-optional discussion threads, CI cancel/runner-revoke/variables/tenant-wide pipelines, environments polish, notification deep-links); the client restructured to build-once micro-FE emission (per-surface ESM bundles + import-map vendor sharing, editions assembled by manifest-driven file selection, exclusion provable as asset absence, a playwright boot smoke); and the fresh-claimed zero-project instance made a first-class onboarding state (idempotent tenant genesis + βcreate your first {Team}β + project switcher) | β Done |
| M17 - Work-item essentials (workos parity Ia) | The daily-workflow item-model core on the board aggregate: rich-text description (markdown), comments (flat threads, @mentions, reactions, edit/delete), a per-item activity feed, stable human-readable item keys (PROJ-123, a project-scoped guard-table mint), board-global rank + drag-to-rank (opaque fractional index, a rankBetween client helper golden-twinned with the server), reporter, flag/blocked marker, unarchive + archived view, and permission-visibility (the /client-config permissions list); plus the absorbed M16 T12 (card-detail route/permalinks, person picker + names everywhere, transition widening/hiding, blob FieldInput, board filters) and the client restructure (views/ split, ui-kit adoption, one shared FieldInput). The flagship M17AcceptanceSuite walks the whole card lifecycle over the wire | β Done |
| M18 - Work-item organization (workos parity Ib) | The taxonomy layer over the M17 item core on the board aggregate: free-form labels with a DISTINCT-registry create-on-type typeahead, first-class priority + item types over pack vocabularies (decide-time-stamped defaults), a single-parent/level-guarded ChildOf epic hierarchy with a client-fold done/total roll-up, the standard link kinds (Blocks/Duplicates/Relates(symmetric)/Clones) + web links, watchers as a stream fold with decider auto-watch + comment/move/assign fan-out, first-class attachment lists (drag/paste/thumbnail/lightbox, two-probe orphan-GC), field-schema depth (defaults/multi-select/URL/datetime/user-picker), clone, and move-between-projects with key repoint. The flagship M18AcceptanceSuite walks the whole vocabulary over the wire | β Done |
| M19 - Agile substrate (workos parity IIa) | The engine half of agile planning on the board aggregate + the new planning capability unit (surface-less until M20): a kernel CQL language on the M8 Expr AST (save-time typecheck, a Scala/TS twin evaluator over read models) + saved filters; a per-project sprint aggregate + backlog query + rank rebalance + estimation/velocity; status categories + resolution + per-edge transition guards; nine report folds behind a ColumnEntryReads seam; a share-by-link dashboard aggregate; versions/components + project leads; worklogs + FieldType.Duration; the pack-configured automation engine (auto-assign, a generic rule reactor with card-tier whenQuery, scheduled-query over a saved filter); and custom link kinds + votes. The flagship M19AcceptanceSuite scripts the substrate over the wire | β Done |
| M20 - Agile screens (workos parity IIb) | Every surface over the M19 engine: the CQL navigator + saved-filter management; board-face depth (quick-filter chips, swimlanes, epic name/color, category-grouped columns, resolution prompt, card layout/colors, density/collapse, count badges); backlog + sprint screens + capacity indicator + the catalogue-gated sprint chip; list/table + calendar views; the reports + dashboards surfaces (a ui-kit chart language); version panels; timeline polish (pointer drag-to-schedule, sprint/version markers, dependency conflict flags, zoom, hierarchy expand); and the field/link machinery UI (a shared FieldInput with cascading/radio/checkbox/toggle/multi-user/duration/version arms, the custom-kind chooser, the move column-mapping step, the vote button, the worklog panel). Ships planning-ui + the four planning.* surfaces; no new server vocabulary | β Done |
| R-I / R-II - Repository topology (structural, no milestone number) | The monorepo restructured into eight sibling repositories β one distribution repo (emporium) composing editions from a digest-verified workspace store, seven primitive repos (core kernel Β· machina platform Β· the five capability groups) each self-testable from its own clone against downward store artifacts only (the one-way test DAG). Units contribute endpoints/OpenAPI/adapters/permissions/migrations/daemons through a UnitOutputs plug so the platform depends on the kernel alone; one node edition compiler emits a committed per-edition lock + plan that sbt and the client assembler both read; per-owner Flyway histories baseline against the frozen V1..V38 ledger; producer-owned descriptors are registry-parity-gated. Extraction ran kernel-first, platform-last; versions pin 0.1.0 (evict + republish), a group ships as one candidate integrated by a single lock-update PR | β Done |
| M21 - Forge repo & MR depth (forge parity I) | The forgeβs CORE floor completed, and the first proof of the split (fornax primitive candidates + two machina candidates, integrated by lock-update PRs, no version bump): SSH transport (Apache MINA as a unit daemon; SSH/GPG/deploy-key + deploy-token management), protected branches + tags + push policy as one pure PushPolicy behind ONE ref-write gate shared by HTTP/SSH/merge/REST, repo lifecycle (rename/transfer/unarchive/delete-with-grace + a web+git redirect table off the UUID-on-disk seam), web file editing (in-core commit-with-actions β branch/MR, cherry-pick/revert), merge methods (squash/rebase/FF behind the ref CAS), review depth (side-by-side diff as a client renderer over the hunk JSON, multi-line/batched review, sha-bound approvals that stale on push, all-threads-resolved gate, draft MRs, templates, CODEOWNERS, auto-merge-when-green), git-reads depth (blame, per-path history, permalinks + line anchors, archive/raw/patch), cross-repo content search (a unit-contributed perm-tagged FTS fold + a content-indexer daemon), releases + Git LFS (the first orphan-GC probe), and commit-signature verification | β Done |
| M22 - Forge platform + the first cross-group bridge (forge parity II) | Everything that makes the forge a platform, led by the two-product story on one log: the repoβtracker bridge β commit/MR closing keywords (Closes OPS-1), autolinks, create-branch/MR-from-card, and the work-item dev panel (branches/commits/MRs/pipelines/pages as one fold) via the selectable devlink unitβs saga reactor over tabulaβs guarded board ports + a declarative shell extension slot (a consumer-owned port over a producer contract, UI by slot never a cross-group import β the pattern every later bridge follows); container/npm/generic registries (OCI v2, rootless kaniko builds) + browse UI; CI completion (cron schedules, matrix/parallel, service sidecars, allow_failure, [skip ci], include/extends, artifact expiry + browser, JUnit/coverage reports, status badges, OIDC id_tokens for keyless deploys, scoped variables, per-MR review apps + rollback); collaboration (a git-backed wiki as a repo kind in code + an event-sourced pages unit in tabula; snippets, star/watch, profiles + contribution graph, RSS); push mirroring; a commit-status API + required checks for external CI; templates/import; secret-detection; instance-signed web commits; a scope-aware per-repo/group webhooks unit; and the new combined internal-ops edition (forge βͺ workos + devlink + pages + webhooks) β proven by M22BridgeJourney (the composed outbox-scope crossing) + fornaxβs first M22AcceptanceSuite (the bridge over a real board) | β Done |
| Beyond M22 | Next: M23 self-served product floor + licensing (email, admin area, invites + scoped roles, PAT hardening, rate limits, bulk/CSV; then signed offline Ed25519 keys bound to editions β never a dependency of the release) β Checkpoint C1, the self-served release (every edition published as versioned images + bundles at the parity docsβ CORE + EXPECTED bar). After C1: M24 integrations & customisation (the service doorway, connectors, importers, custom editions), the trigger-gated R-III release plumbing (remote store, CI-side publishing, signing), M25 BYOC agent-first, M26 scale-out profiles | Planned |
Keywords
- Languages:
Scala 3Β·TypeScriptΒ·SQL - Architecture:
Event SourcingΒ·CQRSΒ·Single System of RecordΒ·Multi-TenancyΒ·Optimistic ConcurrencyΒ·Declarative Configuration / PacksΒ·Config-Selectable SurfacesΒ·Module CatalogueΒ·Process Managers / SagasΒ·Exactly-OnceΒ·Pack-Swap ConfigurabilityΒ·Durable Replay-Safe TimersΒ·Off-Log Side-Stores (Reference-by-ID)Β·Envelope EncryptionΒ·Cross-Surface Full-Text SearchΒ·Capability RegistryΒ·Typed Rules-DSL (Total, Data-Encoded, Typecheck-at-Load)Β·Typed Query Language (CQL, Parser onto a Shared AST, Typecheck-at-Save)Β·Fold-Only Report ModelsΒ·Pack-Configured Automation EngineΒ·Git Smart HTTP (JGit)Β·Cargo Sparse RegistryΒ·Read-Your-Writes Inline FoldΒ·Per-Environment Origin IsolationΒ·Content-Addressed Static ServingΒ·Provider-Agnostic Deploy Targets - Server:
Cats Effect 3Β·http4sΒ·TapirΒ·DoobieΒ·FlywayΒ·circeΒ·jwt-scalaΒ·Postgres / JSONB - Domain:
No-Double-Book Reservation CoreΒ·Interdependent Resource Graph (DAG)Β·Kit ExpansionΒ·Workflow State MachineΒ·WIP LimitsΒ·Event-Level Last-Writer-WinsΒ·Work-Item Taxonomy (Labels Β· Priorities Β· Typed Hierarchy)Β·Fractional-Index RankingΒ·Typed + Custom Link GraphΒ·Watcher & Voter Fan-OutΒ·Guard-Table Key Mint + RedirectΒ·Sprints / Backlog / VelocityΒ·Status Categories + ResolutionΒ·Transition Guards (CQL)Β·Worklogs / Derived-RemainingΒ·Versions & Components - Live read-side:
WebSocket Server-Ordered Fan-OutΒ·LISTEN/NOTIFY Event-Log FeedΒ·Reconnect Catch-Up (dedup-by-position)Β·Ephemeral PresenceΒ·Framework-Free sync-client - Contract-first:
Tapir β OpenAPIΒ·openapi-typescript codegenΒ·CI drift gate