Repository navigation
v0.3.0
Pre-releaseThe release in which a minted name can still be deleted, until it is published.
There was no delete anywhere before — this is a system that declares NR (never
reassign). But NR binds the names you have handed out, not a name at the instant
it is minted. Numbering a draft object ahead of time is ordinary practice, and when that
registration is called off, leaving a number nothing points at in the ledger forever
is not what keeping the promise looks like.
The boundary is a single Ark.published_at, and it is one-way: once published, it
cannot be deleted — except through POST /api/purge, which the registration authority's
operator may use and which always leaves a trace. The default is still "publish on
mint", so existing callers need no change, and every existing ARK migrates as
published.
Also fixed: alembic upgrade head did not run on SQLite. The exact steps in the
Quickstart had been stopping partway for three releases — because we had only ever
round-tripped on PostgreSQL.
Added
-
An ARK can be deleted before it is published. There used to be no delete anywhere:
declaringNR(no re-assignment) means resolution must never stop. But whatNR
binds are the names that went out into the world, not every name the moment it is
minted. Reserving a number for an object that is still a draft is ordinary practice,
and when such a deposit is abandoned, a number that points at nothing forever is
not keeping the promise either.So
Ark.published_atwas added.nullmeans "not published yet": the ARK does not
resolve — the resolver answers as it does for a name it has never seen — and it
can be deleted.POST /api/mintwith{"reserve": true}— mint it without publishingPOST /api/publish— publish it globally. From here on it cannot be deletedPOST /api/delete— withdraw one that was never published (a published one is409)arkhe ark publish/arkhe ark delete, and the same two actions on the ARK page of
the admin interfaceARKHE_RESOLVE_UNPUBLISHED— a resolver inside a closed network resolves them
The boundary only goes one way. Publishing cannot be undone; if it could, deleting
before publication would mean nothing. The default still mints and publishes in one
step, so existing callers need no change, and every existing ARK migrates as
published.Whether it resolves is not decided by the ARK's state alone — it depends on which
resolver is answering. A resolver started withARKHE_RESOLVE_UNPUBLISHED=1, inside a
closed network, does resolve reserved ARKs: a name minted in that network is
worthless if the network's own resolver will not resolve it, which would defeat the
point of giving closed objects the same shape of PID. The default does not, because
?infoand??need no authentication and the safe side belongs in the default.A withdrawn name is not freed. It moves to
withdrawn_nameand is never assigned
again, by minting or by import: a reserved identifier has usually already been handed
to someone — that is what reserving is for — and re-using it would be
indistinguishable, from outside, from breakingNR. Deletion also has its own scope,
ark:delete; being able to mint and being able to withdraw are different decisions. -
One narrow way out for a published ARK (
POST /api/purge,arkhe ark purge,
ark:purge).
Everything here exists so that a published identifier keeps resolving, and a
published ARK not being deletable is the centre of that. The door is nonetheless
open because reality sometimes brings a demand that outweighs an identifier — a
removal order, personal data that should never have been published, a mass ingest
that went in wrong. Without a way out, someone ends up deleting rows straight from
the database, and a deletion that leaves no trace is the worst kind.So it is not made impossible; it is made narrow and recorded:
- the registration authority's operator only (
ark:purgeand
authority=system) — never a NAAN administrator, never an organisation; - a reason is required — a purge that leaves nothing behind is the same as one
that never happened; confirmmust repeat the ARK, so a script walking a list cannot empty the
ledger by accident;- the name is not freed — it moves to
withdrawn_nameand is never assigned
again; - the whole thing is audited.
The last two are what survive. The target and the description go, but the name can
never come to mean something else: a stale reference gets404, never a different
object.NRholds; what breaks is "keeps resolving".The ORM enforces it too. A published row cannot be deleted unless the session has
named that one ARK as the one being purged (models.sanctioned_purge). A global
flag would get left raised, and you would find out only after a row that must not
disappear had disappeared. - the registration authority's operator only (
Changed
- An invariant is stated more narrowly. "An ARK is never deleted" is now "a
published ARK is never deleted". Nothing that was protected has been given up — a
name that went out still cannot go — but the promise has been rewritten to say exactly
what it covers, and the versioning
policy was updated to match.
Fixed
-
alembic upgrade headdid not run on SQLite. The steps written in the Quickstart
(ARKHE_DATABASE_URL=sqlite:///…, thenalembic upgrade head) stopped at the third
migration withNotImplementedError. SQLite has noALTERthat adds or drops a
constraint, socreate_foreign_keyanddrop_constrainthave to go through batch
mode — the copy-and-move strategy — and a partial index'swhereclause has to be
sa.text()rather than a bare string.It had been broken for three releases. Round-tripping only against PostgreSQL hid
it: that stays the authoritative check, but the steps the documentation gives have
to be known to work on their own.tests/test_migrations.pynow runs
upgrade → downgrade base → upgradeon SQLite and compares the migrated schema's
tables and columns against what the models declare.PostgreSQL behaviour is unchanged —
batch_alter_tableemits the same plainALTER
there. The widening migration still does nothing on SQLite, which does not enforce
varchar lengths; rebuilding tables that carry primary and foreign keys to change a
number SQLite ignores is not worth the risk (alembic checkagainst SQLite reports
exactly that difference). -
The example ARKs in the documentation were not identifiers this ledger can mint.
The reference and concept pages showedark:99999/x9abc— a three-character blade, no
check digit, and ana, which betanumeric does not contain. Only the walkthrough
showed a real one (ark:99999/c7w545sj4z5), so the pages disagreed with each other
about how long a name is. Readers learn the shape from the examples, and the shape
being taught was onemintcannot produce.Every example is now a shoulder plus eight betanumeric characters plus a check digit,
computed with the implementation's ownnoid_check_digit.ark:99999/x9tn1qkq2g7—
the name the walkthrough actually mints — now runs through the whole site, and the
mistranscription example is one character away from it (…g8), so whyARKHE-1403is
a different answer from "no such ARK" can be read off the example itself. The examples
inside the OpenAPI descriptions moved with them.A test holds the line (
test_docs): everyark:99999/…in the documentation and
in the generated OpenAPI must be betanumeric and must verify. The two deliberately
wrong ones are listed with the reason each exists, and the test also checks that they
still fail and are still in the documentation — a stale allowance cannot open a hole
quietly.
日本語の変更履歴
· Full Changelog: v0.2.0...v0.3.0