Files
portal/docs
Bendik Aagaard LynghaugandClaude Opus 5 d5de25e8c6 A file can come back out, and a script cannot come back forever
Two halves of the same evening.

Uploads were one-way. A `type: file` field put an object in the bucket
and wrote its key into the record, and nothing ever read it back - a
desk showed `0aba5734-...-drawing.pdf` as a string with no link, so a
builder could receive drawings and never open one.
`GET /attachment/{bucket}/{record}/{field}` streams it. The key is not
the credential and is not taken from the caller: it is read out of the
record named, so a file is reachable only through a record somebody is
allowed to see, and a key that leaks off a desk is a link to nothing.

And there was no rate limiting anywhere. A burst of 30 per caller IP,
refilled one every two seconds, outside the session layer so anyone
over it is turned away before a handler is entered. Well above a
person filling in a form - a page load fetches several resources at
once - and well below being a nuisance. PORTAL_RATE_BURST and
PORTAL_RATE_SECONDS retune it; either 0 turns it off for an instance
behind something that already does this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-28 16:28:43 +02:00
..

portal documentation

Portal turns a Git repo of YAML into a running site. Almost everything here is about that YAML: what a content repo may say, and what the engine does with it.

Architecture What the engine is made of and where each piece lives in the source.
Content reference Every key a content repo may write, and what it does.
State machines aggregates.yaml: stages, who moves a case, mail, deadlines, memberships.
Access How the Cedar policy is compiled from content, and who may ask it what.
Operations Releasing, deploying, adding a site, environment variables.
Filesystem routes Why the questions/ tree is the router.

Two repos in the same family carry their own docs:

  • uhhm/iris — the lint. Versioned as portal and released by portal's publish job; it is the thing a content repo's CI runs before anything reaches a site.
  • uhhm/gdo — the mailer. Delivers what content asked to be sent, and carries replies back.