Contribution Date
Contribution Project
Contribution Details
Events that actually fire, a receiver a developer can register, and a 202 nobody could read
The outbox and the sender existed; nothing produced into one and nothing
administered them. This is the half that makes them a feature rather than a sixth
guard rail with no road.
Six event kinds in one place, because a subscription filters on these strings: a
producer that invented asset.publish beside asset.published would leave every
filtered subscription silently missing half its events, and the mistake is
invisible until a customer notices their CMS is out of step. Past tense
throughout — an outbox row is written after the change, so every kind is a
statement about something that already happened.
Emitted from the real code paths, and from both of them where there are two. A
metadata edit goes through the single-asset endpoint and through the bulk
executor, and a consumer cannot tell which route an edit took — an event that
fired for one and not the other would be a cache that goes stale depending on how
many assets somebody selected. A no-op emits nothing: re-publishing an
already-published asset changes nothing and must announce nothing, or a consumer
ends up doing our idempotence for us.
Payloads carry ids and never bytes, which is §11's reference-not-copy premise. A
metadata event carries the keys that changed rather than the values — a receiver
that wants them reads the asset with its own credential and gets what it is
allowed to see, whereas a fat payload is damrs deciding at write time what an
endpoint's scope will be at read time.
Then the SSRF guard exposed a defect the moment I used it. It refused
http://127.0.0.1:9099/hook — the shape of every receiver a developer writes — so
building a webhook integration locally was impossible without hand-written SQL, a
workaround no customer has. Development now permits http and loopback, and
nothing else: private and link-local stay refused everywhere, because a
development box is often a cloud VM and 169.254.169.254 is the metadata service.
Reach is three levels rather than a boolean now, since collapsing loopback and
private into "internal" was the mistake.
The web client special-cased 204 alone, so the first endpoint to answer 202 with no
content threw a JSON parse error inside a successful call — surfacing as "could not
retry" for a retry that had worked. It reads the body and decides from that now,
which fixes it for every future no-content response rather than for this one.
And cargo fmt collapsed a line-continued string literal while keeping its padding,
putting "post to one even in development" in a user-facing refusal.
Caught by a test asserting the sentence; I then checked every literal in the file
for the same damage.
Verified end to end against the running stack with an independent Node receiver:
two publications and a metadata edit delivered, every signature VERIFIED using
only the documented scheme and a fresh timestamp, a deliberate 503 retried to
success with the same delivery id, and the metadata payload carrying ["title"]
while the value appeared nowhere. 2 producer cases, 2 more db cases, 9 browser
cases including axe.
Contribution Issue Link
Files count
0
Patches count
1