Skip to main content

Decision records

Non-trivial changes to DocStack are recorded as architecture decision records in specs/adr/. Some are decisions; some are findings dispatched from applications built on DocStack, kept because the fix they led to is only legible next to the failure. The numbering is sparse on purpose: 0001 and 0002 are DocStack's own first records, and 0003 through 0017 were never in this repository.

#TitleStatusDateIn one line
0001Sync belongs to DocStack, transports do notaccepted2026-08-24remote is any PouchDB database; DocStack owns the lifecycle, filters and the schema gate, and never takes a transport dependency.
0002stack.db is a guarded handleaccepted2026-08-24Writes that skip the authoring path throw StackWriteGuardError; replication uses an internal handle.
0018The document key lifecyclefinding, accepted2026-08-24DocStack never invents document keys; a keyless stack opens locked; the canary is the admission test.
0019StackPlugin pristine capturefinding, fixed2026-08PouchDB installs core methods per instance; the plugin receives the originals as an argument.
0020Change events carry ciphertextfinding, fixed2026-08Live subscriptions decrypt before delivery; ciphertext belongs to replication, never to a read.
0021One changes feed per stackaccepted2026-08-25Subscribers demultiplex one feed; building a class does not subscribe it.
0022Findings: @docstack/react 0.0.9findings, addressed2026-08-26The provider raced itself under double effects; hooks reported "loaded" during startup.
0023Findings: @docstack/client 0.1.6findings, fixed2026-08-26Sequential ids lost writes under replication; log records and internal documents leaked to the remote.
0024Random document ids, and replicating only what binds two instancesaccepted2026-08-26Ids are Type-<24 hex>; what replicates is what the peer cannot already derive.
0025Proposal: make useQuerySQL liveproposal, implemented2026-08-26Subscriptions derived from the query's AST.
0026Live SQL views, and the subquery paths that never ranaccepted2026-08-26useQuerySQL is live by default; IN, NOT IN and EXISTS subqueries fixed and pinned.
0027Log records recognised by shapeaccepted2026-08-26Pre-existing bare log records stay local; the default sink level drops to warn.
0028Ephemeral and simple classesaccepted2026-08-26Two class flags: purged on open and never replicated; stored as given with no pipeline.
0029Proposal: hub architecture supportproposal, dispatched2026-08-28Cross-origin convergence and tenancy declared on the model.
0030The channel is an adapter, a tenant is a stackaccepted2026-08-28Topology is configuration; a tenant is its own database; keys move with grants or the grant is fiction.
0031Scheduling jobs on a clientaccepted2026-08-28An allow-listed scheduler the application starts; missed occurrences collapse; cron refused.
0032Reads decrypt again, and a policy arms on active: trueaccepted2026-09-01The decrypting get override restored; the legacy rule engine's active contract confirmed.
0033DocStack.sync() binds to the stacks that existed when it was calledfinding, fixed2026-09-01A workspace mounted after sync() replicated nothing while every status read healthy.
0034Late stacks join a running syncaccepted2026-09-01An un-scoped sync() is a standing instruction; getSyncCoverage() tells idle from unbound.
0035useFind never applies an empty resultfinding, fixed in react 0.1.12026-09-01A list could never lose its last row; staleness is now owned by a run counter.
0036applySchemaDelta applies one attributefinding, fixed2026-09-03Propagation returned from inside its loop and skipped in-place edits.
0037A class patch should say what changedproposal, accepted in property2026-09-03Restating a class dropped whatever the restatement forgot.
0038A class patch merges its schema, and null drops an attributeaccepted2026-09-03Every delta entry applies; schemas merge attribute by attribute.
0039Transactions stage above the plugin and commit through itaccepted2026-09-03Named write transactions with overlay reads and reported atomicity.
0040Sync on a locked stack: three junctionsfinding, resolved2026-09-03The consumer schema gate; locked deferral of class patches; revision-addressed reads serve the stored form.
0041The patch ledger arms on activeaccepted2026-09-03A ledger entry records success, deferral or a legacy application; failures retry.
0042A patch chain applies through one internal transactionaccepted, implemented2026-09-03Chains compose in memory and land as one batch; all-or-nothing.
0043bulkDocs class resolution ignores the batchfinding, fixed2026-09-04A patch can introduce a class and seed its first document in one batch.
0044A patch carries one-shot jobsaccepted, implemented2026-09-04preApply and postApply migration jobs, staged with the model.
0045Access control is cryptographic: CP-ABE scopes beside the engineaccepted, implemented 2026-09-062026-09-04One access-control language, enforced by decryption; the rule engine is removed, @docstack/abe carries the primitive.

Specs

Reading them

An ADR states a decision, the reasoning, and the consequences, and names the tests that pin it. When a page on this site makes a claim about behaviour, the ADR it links is where the claim is argued. If you change code that an ADR describes, update or supersede the ADR in the same change.