Conform to standard.site lexicon spec for publication + document records#407
Merged
Conversation
The validator at standard.site reported \`required field missing: site\` on our document records. Investigation surfaced multiple field-name deviations on both record types — we'd been emitting \"close enough\" shapes that worked for lenient clients but failed strict validation. \`site.standard.publication\` per <https://standard.site/docs/lexicons/publication/>: required: url, name optional: icon (blob), description, basicTheme, labels, preferences Was emitting: title (s/b \`name\`), cover (s/b \`icon\`), createdAt (not in spec at all). Fixed to spec; \`description\` is now \`Option<String>\` to match \"optional\". \`site.standard.document\` per <https://standard.site/docs/lexicons/document/>: required: site, title, publishedAt optional: path, description, coverImage, updatedAt, tags, ... Was emitting: publication (s/b \`site\` AND as a plain URI string, not a strong-ref), url (s/b \`path\`, optional), cover (s/b \`coverImage\`, optional). Fixed: \`site: String\` holds the publication URI, \`path\` is the URL segment relative to the publication URL (\`/<canonical>\`), \`updatedAt\` made optional. The \`atproto_pub_cid\` machinery from #406 stays — its semantics shift from \"spec-correct strong-ref cascade\" to \"trigger doc re-emission when publication record content changes.\" Useful in exactly this kind of schema-migration scenario: the next deploy after this merges will detect \`cover_synced = false\` → re-put publication with new schema → new cid → all 43 docs detect drift → all re-put with new schema. Also flips \`publications.toml\`'s \`cover_synced\` to \`false\` so the migration triggers on the next deploy without manual intervention. Bluesky external-embed \`associatedRefs\` still emits StrongRefs — that's a separate spec on the Bluesky side and is out of scope for this PR. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
coreyja
approved these changes
Jun 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The standard.site validator surfaced `required field missing: site` on document records. Investigation found multiple field-name deviations on both record types — we'd been emitting "close enough" shapes that lenient clients accepted but strict validation rejected.
Publication record fixes (spec: publication lexicon)
Document record fixes (spec: document lexicon)
The big design simplification
standard.site documents reference their publication via a plain URI string, not a StrongRef with cid. That means my `atproto_pub_cid` cascade work in #406 was solving a problem the spec doesn't have — when the publication content changes, document `site` strings stay valid because URIs are stable.
But the cascade machinery turns out to be exactly the right thing for this migration. Repurposed:
Migration on merge
`publications.toml` flipped `cover_synced = false`. The next deploy:
No manual steps. After this lands, run the standard.site validator against any `look-ma-no-ai` URL again and it should pass.
Out of scope (separate PR)
The Bluesky external-embed `associatedRefs` field still emits `StrongRef` shapes. That's a separate spec on the Bluesky side, not standard.site. Leaving it untouched until/unless validation flags it.
🤖 Generated with Claude Code