Skip to content

v0.3.0 — collection access policies

Choose a tag to compare

@javimosch javimosch released this 06 Sep 14:58
· 28 commits to master since this release
f6371de

A browser or mobile client can now talk to bkn directly. Every data route used to require the admin token, so the application in between re-implemented verify-token / read-subject / add-tenant-filter at every endpoint — and the day one was forgotten, that endpoint returned everybody's rows.

Collections that know who is asking

bkn store create app/notes --owner-field user_id \
  --access read=owner,create=owner,update=owner,delete=owner

Four verbs × five audiences (admin, user, owner, org, public). admin is the default, so a collection nobody has declared behaves exactly as it did in v0.2.0. A policy grants and never revokes.

  • A scoped create takes its tenancy from the token, not the body. A document cannot be written into the wrong tenant, because the tenant is not something the client gets to say.
  • The scope rides inside the operation — a filter for lists and rollups, a precondition on the compare-and-set patch already performed, ON CONFLICT ... WHERE for upserts. A check that is not part of the write is not a check.
  • Cross-tenant reads, patches and deletes answer 404, not 403: a 403 confirms the id is real to somebody with no right to know it.

Also

  • Self-service POST /v1/auth/register (off unless BKN_OPEN_SIGNUP=1) and /v1/auth/password.
  • Organizations over HTTP — create a workspace, invite members, gated by org role rather than the admin token.
  • PUT /v1/store/{ns}/{coll} declares a collection over HTTP, so a deployment behind a reverse proxy can be administered without a shell on the box.
  • BKN_CORS_ORIGIN — an explicit allow-list, never a reflected origin.
  • Fix: a normalizer on a nested field was accepted and then ignored, leaving a document unfindable by the very field its collection declared as normalized.

Upgrading from v0.2.0

One ALTER TABLE collections ADD COLUMN access. Instant, and rollback needs no undo — the previous binary reads and writes a migrated database.

Verified before release: a differential against a consistent snapshot of production (both binaries, each against its own copy) came back 49 identical, 0 diverged across every collection's records, kv, cron, hooks, scripts, files, auth, locks and event stats; 140 records / 26 collections / 29,757 events preserved; a patch on a real production document byte-identical.

Not in this release

Files are not scoped — user uploads still go through a hook that checks for itself. There is no realtime and no text search.