Skip to content

docs: version the spec by atServer release, with a change history - #393

Merged
cpswan merged 16 commits into
trunkfrom
gkc-spec-versioning
Nov 9, 2026
Merged

cpswan merged 16 commits into
trunkfrom
gkc-spec-versioning

Conversation

@gkc

@gkc gkc commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

- What I did

  • The spec now says it describes atServer 3.20.0 (p3.20.0, 2026-11-04), and how it is versioned
  • New Appendix E: what each production atServer release from 3.0.35 changed in the protocol, newest first, with an empty Unreleased block at the top
  • Every "Since atServer" marker cites the production release that first shipped the change, and links to its block
  • The body describes 3.19.0: otp:list and otp:delete, reserved namespaces, the removal of stream, the atDirectory's HTTP by ALPN, and the older behaviour it had missed (the pol1. challenge, to:, eph/eAtn, mldsa65)
  • The body describes 3.20.0: otp:get's ttl and live-OTP limits, OTP scope on enroll:request, the narrowed keys verb, lastKeyHolderRevokedAt, the notify id and key limits, monitor re-runs, and the connection and HTTP limits
  • A new CI check, tools/check_spec_versions.py, keeps the header, markers and Appendix E in step

- How I did it
See commits. Each block comes from at_server's CHANGELOG between production releases, checked against the code diff between the canaries those releases promoted. Left for later from review: the check reads only "Since atServer" markers (CR3) and does not flag an unlinked Unreleased (CR13), and atDirectory changes are dated by the atServer release that carried them (CR9).

- How to verify it
Markdown lint and the new check pass

- Description for the changelog
docs: the spec describes atServer 3.20.0 and lists what each production atServer release changed in the protocol

gkc and others added 9 commits October 23, 2026 13:13
The specification now says which production release of the atServer it
describes, in a header under its title, and how it is versioned. The
new Appendix E lists, newest first, what each production release from
3.0.35 on changed in the protocol, one block per release, each with
its publish date and the canary versions it includes. Releases that
changed nothing on the wire have no block.

A production release runs the code of the canary promoted to it, so a
version released only as a canary is listed under the first production
release that shipped it. Every "Since atServer" marker now cites that
production version and links to its block: 3.16.1 to 3.16.4 become
3.16.5, and 3.17.1 (the earlier name of 3.18.0) and 3.18.0 become
3.18.1. The enroll:link text no longer contrasts 3.18.0 with 3.18.1,
since 3.18.0 never reached production.

The header's date is a placeholder until p3.19.0 is published.
The header names atServer 3.19.0, so the main text now describes what
its code does, each change marked "Since atServer 3.19.0":

- otp:list and otp:delete, otp:put needing full privilege, and OTPs
  that record the namespaces of the enrollment that issued them;
- records in a reserved namespace changing only through the verbs that
  own them, passcodes read only through otp:, and the notify checks on
  key names;
- update:json refusing an atKey owned by another atSign;
- batch: answering an entry it cannot run with AT0003;
- the atDirectory answering HTTP by ALPN on its Atsign Protocol port,
  keeping the atSign in redirects and matching atSigns in canonical
  form.

The stream verb is removed: Appendix B.5 says so, and Appendix D.3 no
longer describes its framing.
tools/check_spec_versions.py fails, naming what it found, when the
header does not name the newest production block of Appendix E or
differs from it in tag or date; when a "Since atServer" or Unreleased
marker links a block that does not exist, or a "Since atServer" marker
outside a code block is not a link; or when a production block lacks
its release line or date, or the blocks are not newest first with
Unreleased at the top. A new workflow runs it beside the markdown lint,
on the same events.
An atServer 3.19.0 refuses to write a key whose name starts with "__"
and has no namespace, so the hidden two-underscore public key form in
section 6.2 now carries one, and the example in section 6.6 is
public:__location.wavi rather than public:__location.
Trunk's fuller description of the otp verb replaces this branch's, and
its row in Appendix A is kept. Its markers now cite production versions
and link their Appendix E blocks: the otp:get rule is since 3.16.5,
where canary 3.16.0 first reached production, and the enroll:request
passcode rule since 3.18.1. The refusal of lookup and llookup of a
passcode, since 3.19.0, is added to it.
p3.19.0 was published on GitHub on 2026-10-26, from the commit c3.19.0
was tagged on, so the header and the 3.19.0 block in Appendix E now
carry that date in place of the placeholder.
The header says the spec describes atServer 3.19.0, so the body now
says what that release does where it still described older behaviour:

- the pol1 challenge a cross-atSign from: is given, and the prover's
  check of it, in sections 9.1, 15.2 and 16.3;
- the to: opening of a connection to another atServer, in 15.1;
- mldsa65 in the pkam grammar, and the algorithm an APKAM pkam: is
  verified under;
- eAtn and eph in the notify grammar;
- the enroll fields signingAlgo, apsk, apskLegacy, metadata and
  apkamPublicKeySignature, the r and rw grants, and the update, listns
  and infons operations;
- stats 16 and 17;
- the atDirectory's 400 for a long URI and the query string a redirect
  keeps;
- what refusing keys named like a reserved namespace means for records
  stored earlier.

The Unreleased block now reads "Nothing is listed here yet.", which no
longer reads as saying at_server's trunk is unchanged.
The check now requires the header to be the line under the title and
the only one in the prose, reports an Appendix E heading that is not a
block heading, reads a block's release line across line breaks, refuses
a date that is not a calendar date, compares a block link's version
text with its anchor, and treats a ~~~ fence as code. The workflow
drops a comment that restated its triggers.
@gkc

gkc commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

@cpswan per your suggestion as discussed a few weeks ago ... the PR includes a workflow to help keep the spec up to date. And it's already out of date, as we've released 3.20.0 in the meantime

gkc added 5 commits November 7, 2026 19:25
Move the header to atServer 3.20.0 and open its Appendix E block.
otp:get refuses a ttl of 0 or one above otp.maxTtlInMinutes with
AT0022, and a new OTP with AT0028 while otp.maxLive are live. An
enroll:request presenting an OTP that records namespaces may ask only
for namespaces those cover, and coverage counts a grant on wavi as
covering x.wavi.
keys answers only the two keys:get requests by which an enrollment
collects its own encryption private key and self encryption key, and
refuses every other keys request with AT0009.
enroll:infons also answers lastKeyHolderRevokedAt, the last revocation
of an enrollment holding the namespace that may have held a namespace
private, and enroll:list marks such an enrollment keyHolder.
A notify id longer than 36 characters is refused with AT0003, and a
client's notify key longer than 255 characters, counting cached:, with
AT0016. monitor sent again replaces the connection's feed. A connection
whose client leaves more than 16 MiB unread is closed, HTTP connections
are capped at 50 with 10 and 30 second deadlines, and the WebSocket
upgrade negotiates no compression.
keys answers AT0015 when the key is not stored, and refuses with AT0009
only on a connection authenticated as an enrollment. keyHolder is shown
to an enrollment's own record only without __manage, and the mark comes
from an update of the advertisement, set before it is stored. A monitor
replay stalls rather than closes a client that stops reading, and a
failed replay closes the connection only outside a batch. An undying
OTP is also freed by spending it or by a caller who may manage it. A
config value below 1 MiB stops the atServer from starting.
@gkc
gkc requested a review from cpswan November 7, 2026 19:40
Comment thread .github/workflows/spec-versions.yml Resolved
ubuntu-26.04 has been generally available on GitHub-hosted runners since
17 September 2026, and ubuntu-latest is moving to it from 24.04 until
19 November. Naming the label keeps the image, and so the python3 the
check runs on, fixed.
@gkc
gkc requested a review from cpswan November 9, 2026 12:05
The job only checks out the repo and runs a standard-library Python
script, which suits the 1 vCPU ubuntu-slim runner, generally available
since 22 January 2026. Its image ships Python 3.12, and the job runs in
seconds, well inside that runner's 15-minute job limit.
@cpswan
cpswan merged commit a7f0b8c into trunk Nov 9, 2026
3 checks passed
@cpswan
cpswan deleted the gkc-spec-versioning branch November 9, 2026 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants