[READ-ONLY] Mirror of https://github.com/flo-bit/contrail. atproto backend in a bottle flo-bit.dev/contrail/
0

Configure Feed

Select the types of activity you want to include in your feed.

Version Packages

github-actions[bot] (Jun 15, 2026, 11:10 PM UTC) 161653ce 74a2d3de

+168 -57
-8
.changeset/feed-prune-skip-idle-ticks.md
··· 1 - --- 2 - "@atmo-dev/contrail-appview": patch 3 - "@atmo-dev/contrail-base": patch 4 - --- 5 - 6 - Stop running the `feed_items` prune sweep on every ingest tick. 7 - 8 - A feed only exceeds its cap right after a feed-mutating record, so the per-tick sweep was a no-op on the vast majority of ticks yet still issued a cutoff `DELETE` per actor (~98% of all D1 queries on one deployment). It now sweeps only when a feed-mutating collection was ingested, plus a recovery pass that becomes due ~6h after the previous one completed and then laps one slice per tick — including on idle persistent streams and the `notifyOfUpdate` path. New `getFeedMutatingNsids(config)` derives the gating set. See `docs/04-feeds.md` for sweep timing (and why the full-pass cadence is interval + lap time, not a hard 6h) and the fan-out promptness trade-off.
-24
.changeset/fts-nsid-keyed-collections.md
··· 1 - --- 2 - "@atmo-dev/contrail-base": patch 3 - "@atmo-dev/contrail-appview": patch 4 - "@atmo-dev/contrail-record-host": patch 5 - "@atmo-dev/contrail-lexicons": patch 6 - --- 7 - 8 - Make NSID-keyed collections work through normal ingestion, not just FTS. 9 - 10 - When a collection is keyed directly by its NSID (no short alias, `collection` 11 - field omitted), the value defaulted to `undefined` everywhere it was read. The 12 - records insert and FTS sync were patched via `resolveCollectionKey`, but the 13 - real ingestion entry points still skipped these collections: `getCollectionNsids` 14 - / `getDiscoverableNsids` / `getDependentNsids` produced `undefined` NSIDs (so 15 - Jetstream never subscribed and backfill never ran), `shortNameForNsid` returned 16 - undefined (so `notify` rejected the URI as "collection not tracked"), and 17 - `validateConfig` rejected the config outright (missing `collection`, dotted key 18 - failing short-name validation). 19 - 20 - `CollectionConfig.collection` is now optional. `resolveConfig` normalizes an 21 - omitted `collection` to the map key, `validateConfig` accepts NSID-keyed entries, 22 - and every collection-list / lookup helper resolves the NSID as `collection ?? key` 23 - so the behavior is correct on both raw and resolved configs. 24 - </content>
-7
.changeset/persist-cursor-before-identity-refresh.md
··· 1 - --- 2 - "@atmo-dev/contrail-appview": patch 3 - --- 4 - 5 - Persist the jetstream ingest cursor before the identity-refresh tail in `runIngestCycle`. 6 - 7 - `saveCursor` previously ran after `refreshStaleIdentities`, whose per-DID network calls can run long. If the ingest isolate was aborted (e.g. a scheduled-invocation deadline) before the save, the cursor never advanced and the next cycle re-drained the same jetstream window indefinitely. Records are durably applied before this point, so the cursor is now saved first; identity refresh is idempotent and staleness-driven, so deferring it past the save is safe.
-10
.changeset/single-jetstream-no-cursor-rollback.md
··· 1 - --- 2 - "@atmo-dev/contrail-base": patch 3 - "@atmo-dev/contrail-appview": patch 4 - --- 5 - 6 - Stop re-ingesting the last 10s on every cron cycle for single-instance jetstream configs. 7 - 8 - `@atcute/jetstream` rolls the cursor back 10s on the first connect when given an array `url`, to absorb clock skew across a pool of interchangeable instances. Contrail's cron ingestion rebuilds the subscription every cycle, so for a single-instance config that once-per-session rollback fired every cycle and redundantly re-delivered the last 10s of events. A new `jetstreamUrlOption` helper hands a one-element config to `@atcute` as a string (one fixed instance, no skew, no rollback) while leaving real multi-instance pools as an array so their cross-instance rollback is preserved. Applied at both subscription construction sites (cron `ingestEvents` and the persistent daemon). 9 - 10 - The per-cycle reconnect log is now accurate for single-instance configs: a reconnect to one fixed instance no longer claims to "pick a URL at random and roll the cursor back 10s" (it can't). The warning now fires only for multi-instance pools and reports the actual `rolled_back` value; single-instance reconnects log at info level confirming no rollback.
+43
packages/contrail-appview/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-appview 2 2 3 + ## 0.12.1 4 + 5 + ### Patch Changes 6 + 7 + - 833a659: Stop running the `feed_items` prune sweep on every ingest tick. 8 + 9 + A feed only exceeds its cap right after a feed-mutating record, so the per-tick sweep was a no-op on the vast majority of ticks yet still issued a cutoff `DELETE` per actor (~98% of all D1 queries on one deployment). It now sweeps only when a feed-mutating collection was ingested, plus a recovery pass that becomes due ~6h after the previous one completed and then laps one slice per tick — including on idle persistent streams and the `notifyOfUpdate` path. New `getFeedMutatingNsids(config)` derives the gating set. See `docs/04-feeds.md` for sweep timing (and why the full-pass cadence is interval + lap time, not a hard 6h) and the fan-out promptness trade-off. 10 + 11 + - 74a2d3d: Make NSID-keyed collections work through normal ingestion, not just FTS. 12 + 13 + When a collection is keyed directly by its NSID (no short alias, `collection` 14 + field omitted), the value defaulted to `undefined` everywhere it was read. The 15 + records insert and FTS sync were patched via `resolveCollectionKey`, but the 16 + real ingestion entry points still skipped these collections: `getCollectionNsids` 17 + / `getDiscoverableNsids` / `getDependentNsids` produced `undefined` NSIDs (so 18 + Jetstream never subscribed and backfill never ran), `shortNameForNsid` returned 19 + undefined (so `notify` rejected the URI as "collection not tracked"), and 20 + `validateConfig` rejected the config outright (missing `collection`, dotted key 21 + failing short-name validation). 22 + 23 + `CollectionConfig.collection` is now optional. `resolveConfig` normalizes an 24 + omitted `collection` to the map key, `validateConfig` accepts NSID-keyed entries, 25 + and every collection-list / lookup helper resolves the NSID as `collection ?? key` 26 + so the behavior is correct on both raw and resolved configs. 27 + </content> 28 + 29 + - 9e01ada: Persist the jetstream ingest cursor before the identity-refresh tail in `runIngestCycle`. 30 + 31 + `saveCursor` previously ran after `refreshStaleIdentities`, whose per-DID network calls can run long. If the ingest isolate was aborted (e.g. a scheduled-invocation deadline) before the save, the cursor never advanced and the next cycle re-drained the same jetstream window indefinitely. Records are durably applied before this point, so the cursor is now saved first; identity refresh is idempotent and staleness-driven, so deferring it past the save is safe. 32 + 33 + - 9894787: Stop re-ingesting the last 10s on every cron cycle for single-instance jetstream configs. 34 + 35 + `@atcute/jetstream` rolls the cursor back 10s on the first connect when given an array `url`, to absorb clock skew across a pool of interchangeable instances. Contrail's cron ingestion rebuilds the subscription every cycle, so for a single-instance config that once-per-session rollback fired every cycle and redundantly re-delivered the last 10s of events. A new `jetstreamUrlOption` helper hands a one-element config to `@atcute` as a string (one fixed instance, no skew, no rollback) while leaving real multi-instance pools as an array so their cross-instance rollback is preserved. Applied at both subscription construction sites (cron `ingestEvents` and the persistent daemon). 36 + 37 + The per-cycle reconnect log is now accurate for single-instance configs: a reconnect to one fixed instance no longer claims to "pick a URL at random and roll the cursor back 10s" (it can't). The warning now fires only for multi-instance pools and reports the actual `rolled_back` value; single-instance reconnects log at info level confirming no rollback. 38 + 39 + - Updated dependencies [833a659] 40 + - Updated dependencies [74a2d3d] 41 + - Updated dependencies [9894787] 42 + - @atmo-dev/contrail-base@0.12.1 43 + - @atmo-dev/contrail-record-host@0.12.1 44 + - @atmo-dev/contrail-authority@0.12.1 45 + 3 46 ## 0.12.0 4 47 5 48 ### Minor Changes
+1 -1
packages/contrail-appview/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-appview", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Public-records appview for contrail — jetstream ingestion, backfill, query layer, feeds, labels, profiles, per-collection XRPC routes.", 5 5 "type": "module", 6 6 "sideEffects": false,
+9
packages/contrail-authority/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-authority 2 2 3 + ## 0.12.1 4 + 5 + ### Patch Changes 6 + 7 + - Updated dependencies [833a659] 8 + - Updated dependencies [74a2d3d] 9 + - Updated dependencies [9894787] 10 + - @atmo-dev/contrail-base@0.12.1 11 + 3 12 ## 0.12.0 4 13 5 14 ### Patch Changes
+1 -1
packages/contrail-authority/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-authority", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Default space-authority implementation for contrail — member list, invites, app policy, credential issuance. Contrail's binary-membership ACL flavor; for ladder-style access levels see @atmo-dev/contrail-community.", 5 5 "type": "module", 6 6 "sideEffects": false,
+32
packages/contrail-base/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-base 2 2 3 + ## 0.12.1 4 + 5 + ### Patch Changes 6 + 7 + - 833a659: Stop running the `feed_items` prune sweep on every ingest tick. 8 + 9 + A feed only exceeds its cap right after a feed-mutating record, so the per-tick sweep was a no-op on the vast majority of ticks yet still issued a cutoff `DELETE` per actor (~98% of all D1 queries on one deployment). It now sweeps only when a feed-mutating collection was ingested, plus a recovery pass that becomes due ~6h after the previous one completed and then laps one slice per tick — including on idle persistent streams and the `notifyOfUpdate` path. New `getFeedMutatingNsids(config)` derives the gating set. See `docs/04-feeds.md` for sweep timing (and why the full-pass cadence is interval + lap time, not a hard 6h) and the fan-out promptness trade-off. 10 + 11 + - 74a2d3d: Make NSID-keyed collections work through normal ingestion, not just FTS. 12 + 13 + When a collection is keyed directly by its NSID (no short alias, `collection` 14 + field omitted), the value defaulted to `undefined` everywhere it was read. The 15 + records insert and FTS sync were patched via `resolveCollectionKey`, but the 16 + real ingestion entry points still skipped these collections: `getCollectionNsids` 17 + / `getDiscoverableNsids` / `getDependentNsids` produced `undefined` NSIDs (so 18 + Jetstream never subscribed and backfill never ran), `shortNameForNsid` returned 19 + undefined (so `notify` rejected the URI as "collection not tracked"), and 20 + `validateConfig` rejected the config outright (missing `collection`, dotted key 21 + failing short-name validation). 22 + 23 + `CollectionConfig.collection` is now optional. `resolveConfig` normalizes an 24 + omitted `collection` to the map key, `validateConfig` accepts NSID-keyed entries, 25 + and every collection-list / lookup helper resolves the NSID as `collection ?? key` 26 + so the behavior is correct on both raw and resolved configs. 27 + </content> 28 + 29 + - 9894787: Stop re-ingesting the last 10s on every cron cycle for single-instance jetstream configs. 30 + 31 + `@atcute/jetstream` rolls the cursor back 10s on the first connect when given an array `url`, to absorb clock skew across a pool of interchangeable instances. Contrail's cron ingestion rebuilds the subscription every cycle, so for a single-instance config that once-per-session rollback fired every cycle and redundantly re-delivered the last 10s of events. A new `jetstreamUrlOption` helper hands a one-element config to `@atcute` as a string (one fixed instance, no skew, no rollback) while leaving real multi-instance pools as an array so their cross-instance rollback is preserved. Applied at both subscription construction sites (cron `ingestEvents` and the persistent daemon). 32 + 33 + The per-cycle reconnect log is now accurate for single-instance configs: a reconnect to one fixed instance no longer claims to "pick a URL at random and roll the cursor back 10s" (it can't). The warning now fires only for multi-instance pools and reports the actual `rolled_back` value; single-instance reconnects log at info level confirming no rollback. 34 + 3 35 ## 0.12.0 4 36 5 37 ### Minor Changes
+1 -1
packages/contrail-base/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-base", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Shared infrastructure for the contrail family of packages — interfaces (SpaceAuthority, RecordHost, CommunityIntegration), credential primitives, binding resolvers, realtime infra, schema scaffolding. No routes, no tables of its own.", 5 5 "type": "module", 6 6 "sideEffects": false,
+10
packages/contrail-community/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-community 2 2 3 + ## 0.12.1 4 + 5 + ### Patch Changes 6 + 7 + - Updated dependencies [833a659] 8 + - Updated dependencies [74a2d3d] 9 + - Updated dependencies [9894787] 10 + - @atmo-dev/contrail-base@0.12.1 11 + - @atmo-dev/contrail@0.12.1 12 + 3 13 ## 0.12.0 4 14 5 15 ### Patch Changes
+1 -1
packages/contrail-community/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-community", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Community module for contrail — community-owned spaces with tiered access levels (member → moderator → admin), invite tokens, DID provisioning, and the access-level reconciler that keeps spaces_members in sync.", 5 5 "type": "module", 6 6 "sideEffects": false,
+27
packages/contrail-record-host/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-record-host 2 2 3 + ## 0.12.1 4 + 5 + ### Patch Changes 6 + 7 + - 74a2d3d: Make NSID-keyed collections work through normal ingestion, not just FTS. 8 + 9 + When a collection is keyed directly by its NSID (no short alias, `collection` 10 + field omitted), the value defaulted to `undefined` everywhere it was read. The 11 + records insert and FTS sync were patched via `resolveCollectionKey`, but the 12 + real ingestion entry points still skipped these collections: `getCollectionNsids` 13 + / `getDiscoverableNsids` / `getDependentNsids` produced `undefined` NSIDs (so 14 + Jetstream never subscribed and backfill never ran), `shortNameForNsid` returned 15 + undefined (so `notify` rejected the URI as "collection not tracked"), and 16 + `validateConfig` rejected the config outright (missing `collection`, dotted key 17 + failing short-name validation). 18 + 19 + `CollectionConfig.collection` is now optional. `resolveConfig` normalizes an 20 + omitted `collection` to the map key, `validateConfig` accepts NSID-keyed entries, 21 + and every collection-list / lookup helper resolves the NSID as `collection ?? key` 22 + so the behavior is correct on both raw and resolved configs. 23 + </content> 24 + 25 + - Updated dependencies [833a659] 26 + - Updated dependencies [74a2d3d] 27 + - Updated dependencies [9894787] 28 + - @atmo-dev/contrail-base@0.12.1 29 + 3 30 ## 0.12.0 4 31 5 32 ### Patch Changes
+1 -1
packages/contrail-record-host/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-record-host", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Default record-host implementation for contrail — stores records and blobs for permissioned spaces, enforces local enrollment as the host's consent layer.", 5 5 "type": "module", 6 6 "sideEffects": false,
+13
packages/contrail/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail 2 2 3 + ## 0.12.1 4 + 5 + ### Patch Changes 6 + 7 + - Updated dependencies [833a659] 8 + - Updated dependencies [74a2d3d] 9 + - Updated dependencies [9e01ada] 10 + - Updated dependencies [9894787] 11 + - @atmo-dev/contrail-appview@0.12.1 12 + - @atmo-dev/contrail-base@0.12.1 13 + - @atmo-dev/contrail-record-host@0.12.1 14 + - @atmo-dev/contrail-authority@0.12.1 15 + 3 16 ## 0.12.0 4 17 5 18 ### Patch Changes
+1 -1
packages/contrail/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Index AT Protocol records with typed XRPC endpoints. Cloudflare Workers + D1, SvelteKit, Node.js.", 5 5 "type": "module", 6 6 "sideEffects": false,
+24
packages/lexicons/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-lexicons 2 2 3 + ## 0.4.14 4 + 5 + ### Patch Changes 6 + 7 + - 74a2d3d: Make NSID-keyed collections work through normal ingestion, not just FTS. 8 + 9 + When a collection is keyed directly by its NSID (no short alias, `collection` 10 + field omitted), the value defaulted to `undefined` everywhere it was read. The 11 + records insert and FTS sync were patched via `resolveCollectionKey`, but the 12 + real ingestion entry points still skipped these collections: `getCollectionNsids` 13 + / `getDiscoverableNsids` / `getDependentNsids` produced `undefined` NSIDs (so 14 + Jetstream never subscribed and backfill never ran), `shortNameForNsid` returned 15 + undefined (so `notify` rejected the URI as "collection not tracked"), and 16 + `validateConfig` rejected the config outright (missing `collection`, dotted key 17 + failing short-name validation). 18 + 19 + `CollectionConfig.collection` is now optional. `resolveConfig` normalizes an 20 + omitted `collection` to the map key, `validateConfig` accepts NSID-keyed entries, 21 + and every collection-list / lookup helper resolves the NSID as `collection ?? key` 22 + so the behavior is correct on both raw and resolved configs. 23 + </content> 24 + 25 + - @atmo-dev/contrail@0.12.1 26 + 3 27 ## 0.4.13 4 28 5 29 ### Patch Changes
+1 -1
packages/lexicons/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-lexicons", 3 - "version": "0.4.13", 3 + "version": "0.4.14", 4 4 "description": "Generate atproto lexicon JSON (and optionally TypeScript types via @atcute/lex-cli) from a Contrail config.", 5 5 "type": "module", 6 6 "files": [
+2
packages/sync/CHANGELOG.md
··· 1 1 # @atmo-dev/contrail-sync 2 2 3 + ## 0.12.1 4 + 3 5 ## 0.12.0 4 6 5 7 ## 0.11.0
+1 -1
packages/sync/package.json
··· 1 1 { 2 2 "name": "@atmo-dev/contrail-sync", 3 - "version": "0.12.0", 3 + "version": "0.12.1", 4 4 "description": "Client-side reactive watch-store over contrail's watchRecords endpoints. SSE + WebSocket transports, optimistic updates, optional IndexedDB cache.", 5 5 "type": "module", 6 6 "sideEffects": false,