@@ -133,43 +133,70 @@ and
133133`.sync <https://arroba.readthedocs.io/en/stable/source/arroba.html#module-arroba.xrpc_sync >`__
134134XRPC handlers:
135135
136+ - ``ENCRYPTED_PROPERTY_KEY ``, base64-encoded AES-256-GCM key for
137+ encrypting signing and recovery keys in the datastore. Generate with:
138+ \` py import base64 from cryptography.hazmat.primitives.ciphers.aead
139+ import AESGCM
140+
141+ key_bytes = AESGCM.generate_key(bit_length=256)
142+ print(base64.b64encode(key_bytes)) \` `\`
143+
136144- ``REPO_TOKEN ``, static token to use as both ``accessJwt `` and
137145 ``refreshJwt ``, defaults to contents of ``repo_token `` file. Not
138146 required to be an actual JWT. If not set, XRPC methods that require
139147 auth will return HTTP 501 Not Implemented.
148+
140149- ``ROLLBACK_WINDOW ``, number of events to serve in the
141150 `subscribeRepos`` rollback
142151 window <https://atproto.com/specs/event-stream#sequence-numbers>`__,
143152 as an integer. Defaults to 50k.
153+
144154- ``PRELOAD_WINDOW ``, number of events to preload into the
145155 `subscribeRepos`` rollback
146156 window <https://atproto.com/specs/event-stream#sequence-numbers>`__ at
147157 startup, as an integer. Defaults to 4k.
158+
148159- ``SUBSCRIBE_REPOS_BATCH_DELAY ``, minimum time to wait between
149160 datastore queries in ``com.atproto.sync.subscribeRepos ``, in seconds,
150161 as a float. Defaults to 0 if unset.
162+
151163- ``SUBSCRIBE_REPOS_SKIPPED_SEQ_WINDOW ``, number of sequence numbers to
152164 wait before skipping emitting a missing one over the firehose.
153165 Defaults to 300, ie 5 minutes at 1qps emitted events.
166+
154167- ``SUBSCRIBE_REPOS_SKIPPED_SEQ_DELAY ``, seconds to wait before skipping
155168 emitting a missing sequence number over the firehose. Defaults to 120,
156169 ie 2 minutes.
170+
157171- ``BLOB_MAX_BYTES ``, maximum allowed size of blobs, in bytes. Defaults
158172 to 100MB.
173+
159174- ``BLOB_REFETCH_DAYS ``, how often in days to refetch remote URL-based
160175 blobs datastore to check that they’re still serving. May be integer or
161176 float. Defaults to 7. These re-fetches happen on demand, during
162177 ``com.atproto.sync.getBlob `` requests.
178+
163179- ``BLOB_REFETCH_TYPES ``, comma-separated list of MIME types (without
164180 subtypes, ie the part after ``/ ``) to refetch blobs for. Defaults to
165181 ``image ``.
182+
166183- ``MEMCACHE_SEQUENCE_BATCH ``, integer, size of batch of sequence
167184 numbers to allocate from ``AtpSequence `` into memcache. Defaults to
168185 1000.
186+
169187- ``MEMCACHE_SEQUENCE_BUFFER ``, integer, how close we should let
170188 memcache get to the current max allocated sequence number in
171189 ``AtpSequence `` before we allocate a new batch. Defaults to 100.
172190
191+ - ``SUPPORTED_COLLECTIONS ``, comma-separated list of AT Protocol
192+ collection NSIDs. If set, ``com.atproto.repo.listRecords `` returns an
193+ empty response for collections not in this list, and
194+ ``com.atproto.repo.describeRepo `` includes this list in its response.
195+ If unset, no filtering is applied.
196+
197+ - ``DISABLE_GETREPO ``, boolean (true if set to any value), whether to
198+ disable the ``getRepo `` XRPC call entirely for repos older than 12h.
199+
173200.. raw :: html
174201
175202 <!-- Only used in app.py:
@@ -182,6 +209,49 @@ XRPC handlers:
182209Changelog
183210---------
184211
212+ 3.0 - 2026-07-01
213+ ~~~~~~~~~~~~~~~~
214+
215+ *Breaking changes: *
216+
217+ Encrypt signing and rotation keys in the datastore, in ``AtpRepo ``
218+ entities. The old non-encrypted properties have been removed. `See this
219+ GitHub issue <https://github.com/snarfed/bridgy-fed/issues/794> `__ for
220+ migration details.
221+
222+ *Non-breaking changes: *
223+
224+ - Add optional new ``SUPPORTED_COLLECTIONS `` environment variable, a
225+ comma-separated set of NSIDs.
226+ - Add SSRF protection to all outgoing HTTP requests via
227+ `requests-hardened <https://github.com/saleor/requests-hardened >`__.
228+ - ``datastore_storage ``:
229+
230+ - ``read_blocks_by_seq ``: set explicit 30s timeout on datastore query.
231+ Evidently, maybe, in rare cases, datastore queries can hang
232+ indefinitely if they don’t have an explicit timeout
233+ (`snarfed/bridgy-fed#2367 <https://github.com/snarfed/bridgy-fed/issues/2367 >`__).
234+ - New ``read_many_raw `` method: bypasses ndb model instantiation and
235+ uses the raw Datastore gRPC stub directly for significantly faster
236+ bulk block reads in ``com.atproto.sync.getRepo ``.
237+ - Change ``AtpBlock.decoded `` from DAG-JSON to decoded CBOR object.
238+
239+ - ``storage ``: new ``read_many_raw `` base method with default fallback
240+ implementation.
241+ - ``did ``:
242+
243+ - ``write_plc `` etc: add new optional ``new_rotation_key `` kwarg.
244+ Accept ``EllipticCurvePublicKey `` for ``signing_key `` as well as
245+ ``EllipticCurvePrivateKey ``.
246+ - ``resolve_* ``: thread safety bug fix for caches.
247+
248+ - ``com.atproto.sync.getRecord ``: add the repo’s head commit block, use
249+ its CID as the CAR root.
250+ - ``com.atproto.sync.getRepo ``: drastically optimize, it’s 15-20x faster
251+ or more for large repos, and uses much less memory.
252+
253+ .. _section-1 :
254+
1852552.0 - 2026-02-07
186256~~~~~~~~~~~~~~~~
187257
@@ -199,13 +269,12 @@ Changelog
199269
200270*Non-breaking changes: *
201271
202- Add new feature to allocate sequence numbers from memcache, atomically,
203- backed by the datastore in batches. Reduces datastore contention when
204- writing commits at 5-10qps and higher. Enable by passing a
205- ``MemcacheSequences `` to the ``DatastoreStorage `` constructor; configure
206- with the ``MEMCACHE_SEQUENCE_BUFFER `` and ``MEMCACHE_SEQUENCE_BATCH ``
207- environment variables.
208-
272+ - Add new feature to allocate sequence numbers from memcache,
273+ atomically, backed by the datastore in batches. Reduces datastore
274+ contention when writing commits at 5-10qps and higher. Enable by
275+ passing a ``MemcacheSequences `` to the ``DatastoreStorage ``
276+ constructor; configure with the ``MEMCACHE_SEQUENCE_BUFFER `` and
277+ ``MEMCACHE_SEQUENCE_BATCH `` environment variables.
209278- Add new ``SUBSCRIBE_REPOS_SKIPPED_SEQ_WINDOW `` and
210279 ``SUBSCRIBE_REPOS_SKIPPED_SEQ_DELAY `` environment variables for
211280 ``subscribeRepos `` (firehose) serving.
@@ -253,7 +322,7 @@ environment variables.
253322 continue serving
254323 (`snarfed/bridgy-fed#2150 <https://github.com/snarfed/bridgy-fed/issues/2150 >`__).
255324
256- .. _section-1 :
325+ .. _section-2 :
257326
2583271.0 - 2025-09-13
259328~~~~~~~~~~~~~~~~
@@ -299,7 +368,7 @@ environment variables.
299368 additional overhead per subscriber
300369 (`#52 <https://github.com/snarfed/arroba/issues/52 >`__).
301370
302- .. _section-2 :
371+ .. _section-3 :
303372
3043730.8 - 2025-03-13
305374~~~~~~~~~~~~~~~~
@@ -354,7 +423,7 @@ serve the latest one
354423fix: Use string TID for ``rev ``, not integer sequence number. \* Bug
355424fix: don’t set status to ``null `` if the account is active.
356425
357- .. _section-3 :
426+ .. _section-4 :
358427
3594280.7 - 2024-11-08
360429~~~~~~~~~~~~~~~~
@@ -416,7 +485,7 @@ fix: don’t set status to ``null`` if the account is active.
416485 claims, eg
417486 `lxm <https://github.com/bluesky-social/atproto/discussions/2687 >`__.
418487
419- .. _section-4 :
488+ .. _section-5 :
420489
4214900.6 - 2024-06-24
422491~~~~~~~~~~~~~~~~
@@ -504,7 +573,7 @@ fix: don’t set status to ``null`` if the account is active.
504573 when appropriate
505574 (`snarfed/bridgy-fed#1083 <https://github.com/snarfed/bridgy-fed/issues/1083 >`__).
506575
507- .. _section-5 :
576+ .. _section-6 :
508577
5095780.5 - 2024-03-16
510579~~~~~~~~~~~~~~~~
@@ -544,7 +613,7 @@ fix: don’t set status to ``null`` if the account is active.
544613 - Implement ``getBlob ``, right now only based on “remote” blobs stored
545614 in ``AtpRemoteBlob ``\ s in datastore storage.
546615
547- .. _section-6 :
616+ .. _section-7 :
548617
5496180.4 - 2023-09-19
550619~~~~~~~~~~~~~~~~
@@ -585,7 +654,7 @@ fix: don’t set status to ``null`` if the account is active.
585654 - Drop bundled ``app.bsky ``/``com.atproto `` lexicons, use
586655 `lexrpc <https://lexrpc.readthedocs.io/ >`__\ ’s instead.
587656
588- .. _section-7 :
657+ .. _section-8 :
589658
5906590.3 - 2023-08-29
591660~~~~~~~~~~~~~~~~
@@ -603,7 +672,7 @@ minimal demo code needed to wrap arroba in a fully functional PDS.
603672
604673- …and much more.
605674
606- .. _section-8 :
675+ .. _section-9 :
607676
6086770.2 - 2023-05-18
609678~~~~~~~~~~~~~~~~
@@ -613,7 +682,7 @@ storage. This completes the first pass at all PDS data structures. Next
613682release will include initial implementations of the
614683``com.atproto.sync.* `` XRPC methods.
615684
616- .. _section-9 :
685+ .. _section-10 :
617686
6186870.1 - 2023-04-30
619688~~~~~~~~~~~~~~~~
@@ -631,7 +700,7 @@ Here’s how to package, test, and ship a new release.
631700 ``sh git checkout main git pull ``
632701
6337022. Run the unit tests.
634- ``sh source local /bin/activate.csh python -m unittest discover python -m unittest arroba.tests.mst_test_suite # more extensive, slower tests (deliberately excluded from autodiscovery) ``
703+ ``sh source .venv /bin/activate.csh python -m unittest discover ``
635704
6367053. Bump the version number in ``pyproject.toml `` and ``docs/conf.py ``.
637706 ``git grep `` the old version number to make sure it only appears in
@@ -643,16 +712,18 @@ Here’s how to package, test, and ship a new release.
643712 ``./docs/build.sh ``. Check that the generated HTML looks fine by
644713 opening ``docs/_build/html/index.html `` and looking around.
645714
646- 5. .. code:: sh
715+ 5.
716+
717+ .. code :: sh
647718
648719 setenv ver X.Y
649720 git commit -am " release v$ver "
650721
651722 6. Upload to `test.pypi.org <https://test.pypi.org/ >`__ for testing.
652- ``sh python -m build twine upload -r pypitest dist/arroba-$ver* ``
723+ ``sh uv build twine upload -r pypitest dist/arroba-$ver.tar.gz dist/arroba-$ver-py3-none-any.whl ``
653724
6547257. Install from test.pypi.org.
655- ``sh cd /tmp python -m venv local source local /bin/activate.csh # make sure we force pip to use the uploaded version pip uninstall arroba pip install --upgrade pip pip install -i https://test.pypi.org/simple --extra-index-url https://pypi.org/simple arroba==$ver ``
726+ ``sh cd /tmp python -m venv .venv source .venv /bin/activate.csh # make sure we force pip to use the uploaded version pip uninstall arroba pip install -i https://test.pypi.org/simple --extra-index-url https://pypi.org/simple arroba==$ver ``
656727
6577288. Smoke test that the code trivially loads and runs. \` sh python
658729
@@ -672,7 +743,7 @@ Here’s how to package, test, and ship a new release.
672743 description text box.
673744
67474511. Upload to `pypi.org <https://pypi.org/ >`__!
675- ``sh twine upload dist/arroba-$ver* ``
746+ ``sh twine upload dist/dist/ arroba-$ver.tar.gz dist/arroba-$ver-py3-none-any.whl ``
676747
67774812. `Wait for the docs to build on Read the
678749 Docs <https://readthedocs.org/projects/arroba/builds/> `__, then
0 commit comments