a textual notation to locate fields within atproto records (draft spec) microcosm.tngl.io/RecordPath/
9
fork

Configure Feed

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

actual draft mostly

phil 0077563b bacc29b5

+23 -2
+23 -2
spec.md
··· 7 7 The proposed syntax is *mostly* compatible with Constellation's `source` record field locator syntax. 8 8 Constellation uses a `<collection nsid>:<path>` format for its `source` parameter; *RecordPath* will replace the `<path>` part. 9 9 10 - While the driving motivation for this spec is lexicon-agnostic backlink indexing, it being able to canonically reference field locations in records is broadly useful. 10 + While the driving motivation for this spec is lexicon-agnostic backlink indexing, being able to canonically reference field locations in records is broadly useful. 11 11 12 12 > [!TIP] 13 13 > For example: [Graze Turbostream](https://help.graze.social/en/article/graze-turbostream-1cmhebt/) resolves references from Bluesky posts into a richly-hydrated firehose, an incredibly useful enhancement. ··· 70 70 The RecordPaths are: 71 71 72 72 ``` 73 - $type -- selects: "app.bsky.fee.like" 73 + $type -- selects: "app.bsky.feed.like" 74 74 createdAt -- "2026-04-15T00:00:00.000Z" 75 75 subject -- the entire { uri: .., cid: ..} sub-object 76 76 subject.uri -- "at://did:plc:pxa3amkp7jhfclaads3zud7q/app.bsky.feed.post/3mjkx2hpvqc2t" ··· 209 209 ## 3. Data-model assumptions 210 210 211 211 RecordPath depends on several properties of the atproto [data model](https://atproto.com/specs/data-model) and [lexicon](https://atproto.com/specs/lexicon) system. 212 + 213 + ### `$type` is on unions (and blobs), not on plain object refs 214 + 215 + - **Records** include `$type` at the top level (not included in RecordPaths) 216 + - **Union variants** MUST include `$type` (consistent with lexicon spec) 217 + - **Plain (non-union) object refs**: Lexicon states `$type` *"should not be included in encoded data as a discriminator."* 218 + Since this is only a "should-not" and not a "must-not", valid records are technically allowed to have a `$type` where they shouldn't, and we aren't guaranteed to have a canonical RecordPath for every valid atproto record field. 219 + Hopefully record serializers are following this SHOULD :/ 220 + 221 + ### Forward-compatibility 222 + 223 + Lexicon evolution rules forbid **type changes** across schema revisions, so a plain object ref cannot be converted to a union in a lexicon-forward-compatibility-compliant revision under the same NSID, so RecordPath canonicalization is hopefully safe from forward-compatible lexicon changes. 224 + 225 + 226 + todo: 227 + 228 + - api recommendations for scalar vs vector queries 229 + 230 + > A RecordPath is *scalar* if it contains no `[]` qualifiers, otherwise *vector*. Implementations that evaluate RecordPaths against records typically expose apis for blah blah 231 + 232 + - maybe compare to DOM `querySelector` / `querySelectorAll`