docs/lexicons.md: the boards as Atmosphere records, one day #217

Merged
Grandiras merged 2 commits from issue-198-lexicons into main 2026-09-22 21:14:56 +00:00
Owner

Part of #198. The issue asks that the lexicons start as a page in docs/, not as code, and this is that page. #198 stays open as the tracker for building against Spaces once it is specified.

What's on the page

  • The namespace: app.ponente.kanban.*, owned through kanban.ponente.app. Schemas get published (a com.atproto.lexicon.schema record, found through _lexicon.kanban.ponente.app) only once they're real; anything tried before then goes under .temp..
  • The records, sketched: board, column, card, placement, due, tag, comment and assignment, each keyed by a TID, with at-uri references between them. Only an author can write their record, so the card holds what its author says (the fields CardPermissions already reserves to them), and what anybody may change is a record of whoever changed it. A due date is a YYYY-MM-DD string, not a datetime. What each maps to today, including what doesn't become a record at all: the member list is the space's, and pins/board order are a private preference.
  • Why it waits: Spaces has been an alpha since 2026-08-20, specified as proposal 0016 (Permissioned Data), and it's explicitly not for production. The page designs against the proposal's shape: each member's records live in a per-space permissioned repo on their own PDS, and a space gives access control, not confidentiality.
  • What doesn't port, and what to do now: double positions (the data model has no floats), membership as a join table, encryption at rest as a trust model rather than a feature, soft delete, Everyone visibility, and search/calendar/for-you becoming an AppView-shaped index.
  • Shapes to prefer meanwhile: roles on the grant row, board rights in one place, non-sequential keys in URLs, no new floats, references that could become at-uris.

Checked against the atproto docs (the data model's float rule, the datetime format, lexicon publishing, the style guide's naming and required advice), the Spaces alpha announcement and proposal 0016, and against the entities (Position is a double on Board, BoardColumn and Card).

CLAUDE.md gets a router row for the page. DocumentationTests pass (reachability, Covers paths, size budget: 14,041 of 16,384 bytes).

🤖 Generated with Claude Code

Part of #198. The issue asks that the lexicons start as a page in `docs/`, not as code, and this is that page. #198 stays open as the tracker for building against Spaces once it is specified. ## What's on the page - **The namespace**: `app.ponente.kanban.*`, owned through `kanban.ponente.app`. Schemas get published (a `com.atproto.lexicon.schema` record, found through `_lexicon.kanban.ponente.app`) only once they're real; anything tried before then goes under `.temp.`. - **The records, sketched**: board, column, card, placement, due, tag, comment and assignment, each keyed by a TID, with at-uri references between them. Only an author can write their record, so the card holds what its author says (the fields `CardPermissions` already reserves to them), and what anybody may change is a record of whoever changed it. A due date is a `YYYY-MM-DD` string, not a `datetime`. What each maps to today, including what doesn't become a record at all: the member list is the space's, and pins/board order are a private preference. - **Why it waits**: Spaces has been an alpha since 2026-08-20, specified as proposal 0016 (*Permissioned Data*), and it's explicitly not for production. The page designs against the proposal's shape: each member's records live in a per-space permissioned repo on their own PDS, and a space gives access control, not confidentiality. - **What doesn't port, and what to do now**: `double` positions (the data model has no floats), membership as a join table, encryption at rest as a trust model rather than a feature, soft delete, `Everyone` visibility, and search/calendar/for-you becoming an AppView-shaped index. - **Shapes to prefer meanwhile**: roles on the grant row, board rights in one place, non-sequential keys in URLs, no new floats, references that could become at-uris. Checked against the atproto docs (the data model's float rule, the `datetime` format, lexicon publishing, the style guide's naming and `required` advice), the Spaces alpha announcement and proposal 0016, and against the entities (`Position` is a `double` on `Board`, `BoardColumn` and `Card`). `CLAUDE.md` gets a router row for the page. `DocumentationTests` pass (reachability, Covers paths, size budget: 14,041 of 16,384 bytes). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
docs/lexicons.md: the boards as Atmosphere records, one day
All checks were successful
CI / build (pull_request) Successful in 46s
aeb4d04bd8
Issue #198's design, written down rather than built: the app.ponente.kanban
namespace, a record per board, column, card, tag, comment and assignment,
and why where each lives waits on ATProto Spaces. Then what does not port —
double positions (the data model has no floats), membership as a join table,
encryption at rest as a trust model rather than a feature, soft delete,
visibility — and the shapes to prefer meanwhile, so the steps before it bend
the model towards records.

Part of #198.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review -->
opencode-reviewer requested changes 2026-09-22 21:09:01 +00:00
Dismissed
opencode-reviewer left a comment

🛑 Verdict: request changes — blocking issues below.

A well-researched design page, and nearly all of it verifies: the entity claims (Position doubles on Board/BoardColumn/Card, BoardKey TID addressing, ?card= integer ids, BoardMember grant+role, BoardOrder as a private preference) match the code, and the atproto claims — NSID authority reversal to kanban.ponente.app, the _lexicon. TXT discovery record, the .temp. convention, the no-floats rule with the spec's own encode-as-strings advice, the required evolution rule, and singular record nouns — all check out against the current specs. The router row and Covers paths are valid.

One real problem: the page's central premise is stale. The Spaces alpha went live on 2026-08-20 with a published proposal spec, so "as of September 2026 the published protocol docs do not describe it" is wrong as of merge — and the proposal answers several of the page's open questions (per-user permissioned repos rather than a board-owned repository; access control, not confidentiality). The don't-build advice survives, but the justification needs rewriting. A second, smaller sketch error: a calendar-day due date can't be a datetime-format string.



⏱ 2m 36s · 10 steps · $0.0298 · tokens: 134.5k in / 8.7k out (+177.9k cache-read) · Go: 5h 55% · wk 29% · mo 47%
📜 Full session transcript

🛑 **Verdict: request changes** — blocking issues below. A well-researched design page, and nearly all of it verifies: the entity claims (`Position` doubles on `Board`/`BoardColumn`/`Card`, `BoardKey` TID addressing, `?card=` integer ids, `BoardMember` grant+role, `BoardOrder` as a private preference) match the code, and the atproto claims — NSID authority reversal to `kanban.ponente.app`, the `_lexicon.` TXT discovery record, the `.temp.` convention, the no-floats rule with the spec's own encode-as-strings advice, the `required` evolution rule, and singular record nouns — all check out against the current specs. The router row and Covers paths are valid. One real problem: the page's central premise is stale. The Spaces alpha went live on 2026-08-20 with a published proposal spec, so "as of September 2026 the published protocol docs do not describe it" is wrong as of merge — and the proposal answers several of the page's open questions (per-user permissioned repos rather than a board-owned repository; access control, not confidentiality). The don't-build advice survives, but the justification needs rewriting. A second, smaller sketch error: a calendar-day due date can't be a `datetime`-format string. --- --- ⏱ 2m 36s · 10 steps · $0.0298 · tokens: 134.5k in / 8.7k out (+177.9k cache-read) · Go: 5h 55% · wk 29% · mo 47% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-217/run-2026-09-22T21-06-25-627Z.md) <!-- opencode-reviewed-head:aeb4d04bd874d0003de3d04ceca3613eaa3409fb --> <!-- opencode-verdict:request_changes -->
docs/lexicons.md Outdated
@ -0,0 +6,4 @@
## Why this is a page and not code
The direction (#190) is that one day a board is data on the Atmosphere network rather than rows in one Postgres: a board roughly a **space**, its member list the space's members. That depends on **ATProto Spaces** — the protocol's answer to private data shared by a group — and as of September 2026 the published protocol docs do not describe it. Every record in an atproto repository today is **public**, and almost nothing a member types into a Ponente board is meant to be. So the rule is the one #198 states: **do not build against Spaces until it is specified.** What can be done is to name things now, and to stop adding shapes that will not port.
Collaborator

The premise "as of September 2026 the published protocol docs do not describe it" is no longer true: the Atproto Spaces alpha went live on 2026-08-20 (atproto.com/blog/atproto-spaces-alpha), with the full protocol spec published as proposal 0016-permissioned-data. The advice on this page still holds — the alpha explicitly says not to run production code against it and that breaking changes will happen — but the sentence that justifies the whole page is now confidently wrong, which is the failure mode this repo's docs convention calls out.

The proposal also answers questions this page treats as open, and the answers are worth folding in:

  • Where records live (line 30): Spaces do not put records in a board-owned repository. Each member stores their own records for the space in a permissioned repo on their own PDS; the space is the aggregation of those per-user repos, gated by a space credential from a space authority DID. That dissolves the page's either/or ("the board's repository or its author's") — it is the author's repo, but private and access-controlled, which answers the "who may edit this card" objection differently than the page assumes.
  • Encryption (line 37): the proposal states outright that Spaces provide access control, not confidentiality — not E2EE, services in the path can read the data. That is the guarantee the page says "has to be read, not assumed"; it is now readable, and it is closer to today's model (server-side readable, encrypted in transit) than to "the app's key goes away."
  • The proposal also carries a member-list shape (com.atproto.simplespace, explicit member list, roles) that bears directly on the BoardMember row of the table.

Rewriting the paragraph to acknowledge the alpha — while keeping the don't-build rule, now grounded in "alpha, breaking changes" rather than "unspecified" — would make the page true and stronger.

The premise "as of September 2026 the published protocol docs do not describe it" is no longer true: the **Atproto Spaces alpha went live on 2026-08-20** ([atproto.com/blog/atproto-spaces-alpha](https://atproto.com/blog/atproto-spaces-alpha)), with the full protocol spec published as [proposal 0016-permissioned-data](https://github.com/bluesky-social/proposals/blob/main/0016-permissioned-data/README.md). The *advice* on this page still holds — the alpha explicitly says not to run production code against it and that breaking changes will happen — but the sentence that justifies the whole page is now confidently wrong, which is the failure mode this repo's docs convention calls out. The proposal also answers questions this page treats as open, and the answers are worth folding in: - **Where records live** (line 30): Spaces do *not* put records in a board-owned repository. Each member stores their own records for the space in a **permissioned repo on their own PDS**; the space is the aggregation of those per-user repos, gated by a space credential from a space authority DID. That dissolves the page's either/or ("the board's repository or its author's") — it is the author's repo, but private and access-controlled, which answers the "who may edit this card" objection differently than the page assumes. - **Encryption** (line 37): the proposal states outright that Spaces provide **access control, not confidentiality** — not E2EE, services in the path can read the data. That is the guarantee the page says "has to be read, not assumed"; it is now readable, and it is closer to today's model (server-side readable, encrypted in transit) than to "the app's key goes away." - The proposal also carries a member-list shape (`com.atproto.simplespace`, explicit member list, roles) that bears directly on the `BoardMember` row of the table. Rewriting the paragraph to acknowledge the alpha — while keeping the don't-build rule, now grounded in "alpha, breaking changes" rather than "unspecified" — would make the page true and stronger.
docs/lexicons.md Outdated
@ -0,0 +25,4 @@
| *(a space's member list)* | — | who is on the board, and who runs it | `BoardMember` (grant + role) |
| *(none)* | — | a member's pins and board order (#195) | `BoardOrder` — a private preference, not a record |
Record names are single nouns, per the style guide; references between records are at-uris, because an integer id means nothing outside one database. The fields are plain — a title a `string` with a length limit, a due date a `string` in `datetime` format, a colour a `string` — and few of them `required`, because a required field can never be made optional again and records outlive every schema revision.
Collaborator

A due date cannot be a string in datetime format if it keeps the semantics Card.DueDate deliberately has. The lexicon datetime format requires a full RFC 3339 timestamp with timezone (a bare 1985-04-12 is listed as invalid in the spec), and there is no date-only string format — so a plain calendar day ("due on the 3rd is due on the 3rd for everyone", per the entity's own doc comment) would have to be a plain string with a YYYY-MM-DD convention, not a datetime. As written, the sketch quietly trades away the all-day semantics the codebase went out of its way to keep.

A due date cannot be a `string` in `datetime` format if it keeps the semantics `Card.DueDate` deliberately has. The lexicon `datetime` format requires a full RFC 3339 timestamp with timezone (a bare `1985-04-12` is listed as invalid in the spec), and there is no date-only string format — so a plain calendar day ("due on the 3rd is due on the 3rd for everyone", per the entity's own doc comment) would have to be a plain `string` with a `YYYY-MM-DD` convention, not a `datetime`. As written, the sketch quietly trades away the all-day semantics the codebase went out of its way to keep.
Author
Owner

Both findings were right; fixed in the latest commit.

  1. Spaces: I'd checked the atproto docs index, which doesn't carry the blog or the proposals repo, and missed the alpha. The page now says Spaces has been an alpha since 2026-08-20 (announcement + proposal 0016), keeps the don't-build rule on the alpha's own terms, and designs against the proposal's shape. Records live in each member's per-space permissioned repo on their own PDS, so the card record holds only what its author says (the fields CardPermissions already reserves to the author). Placement, due date and assignment become records of whoever set them, and an admin's power over someone else's card becomes a decision about what to show. The encryption bullet now quotes "access control, not confidentiality" and says what that means for members whose PDS is Bluesky's.
  2. Due date: a YYYY-MM-DD string, with the reason (datetime needs a timestamp and a zone; Card.DueDate is a DateOnly on purpose).
Both findings were right; fixed in the latest commit. 1. **Spaces**: I'd checked the atproto docs index, which doesn't carry the blog or the proposals repo, and missed the alpha. The page now says Spaces has been an alpha since 2026-08-20 (announcement + proposal 0016), keeps the don't-build rule on the alpha's own terms, and designs against the proposal's shape. Records live in each member's per-space permissioned repo on their own PDS, so the card record holds only what its author says (the fields `CardPermissions` already reserves to the author). Placement, due date and assignment become records of whoever set them, and an admin's power over someone else's card becomes a decision about what to show. The encryption bullet now quotes "access control, not confidentiality" and says what that means for members whose PDS is Bluesky's. 2. **Due date**: a `YYYY-MM-DD` string, with the reason (`datetime` needs a timestamp and a zone; `Card.DueDate` is a `DateOnly` on purpose).
Review: Spaces is an alpha with a published proposal; a due date is a day
All checks were successful
CI / build (pull_request) Successful in 50s
084afbf6a9
The page said the protocol docs did not describe Spaces. They do: an alpha
since 2026-08-20, specified as proposal 0016. Its shape answers what the
page left open — each member's records for a space live in a permissioned
repository on their own PDS, and a space gives access control, not
confidentiality — so the records split along CardPermissions' line: the
card holds what its author says, and a placement, a due date and an
assignment are records of whoever set them. A due date is a YYYY-MM-DD
string, since the lexicon datetime needs a timestamp and a zone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review -->
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

Both blockers from the previous pass are resolved. The page no longer claims Spaces is unspecified: it now correctly dates the alpha (2026-08-20), cites proposal 0016 (Permissioned Data), and grounds the don't-build rule in the alpha's instability rather than absence of a spec. The proposal's answers are folded in properly — per-member permissioned repos on each member's own PDS with a space authority (line 32), and "access control, not confidentiality" quoted for the encryption section (line 44). The due-date sketch is fixed: a plain string holding YYYY-MM-DD, not a datetime, with the correct reasoning about the datetime format and no date-only alternative, matching Card.DueDate's deliberate DateOnly semantics. I re-verified the entity claims against the code (Position doubles on Board/BoardColumn/Card, TID Board.Key via BoardKey, DeletedAt soft delete, BoardVisibility.Everyone) — all accurate. Good to merge.



⏱ 0m 47s · 4 steps · $0.0056 · tokens: 29.3k in / 1.3k out (+17.4k cache-read) · Go: 5h 64% · wk 32% · mo 49%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Both blockers from the previous pass are resolved. The page no longer claims Spaces is unspecified: it now correctly dates the alpha (2026-08-20), cites proposal 0016 (*Permissioned Data*), and grounds the don't-build rule in the alpha's instability rather than absence of a spec. The proposal's answers are folded in properly — per-member permissioned repos on each member's own PDS with a space authority (line 32), and "access control, not confidentiality" quoted for the encryption section (line 44). The due-date sketch is fixed: a plain `string` holding `YYYY-MM-DD`, not a `datetime`, with the correct reasoning about the `datetime` format and no date-only alternative, matching `Card.DueDate`'s deliberate `DateOnly` semantics. I re-verified the entity claims against the code (`Position` doubles on `Board`/`BoardColumn`/`Card`, TID `Board.Key` via `BoardKey`, `DeletedAt` soft delete, `BoardVisibility.Everyone`) — all accurate. Good to merge. --- --- ⏱ 0m 47s · 4 steps · $0.0056 · tokens: 29.3k in / 1.3k out (+17.4k cache-read) · Go: 5h 64% · wk 32% · mo 49% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-217/run-2026-09-22T21-13-07-398Z.md) <!-- opencode-reviewed-head:084afbf6a9b09283022ac5aa3e215c377cb62309 --> <!-- opencode-verdict:approve -->
Grandiras deleted branch issue-198-lexicons 2026-09-22 21:14:56 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/Ponente!217
No description provided.