Repository navigation
Library staff attribution, restricted runtime, and CDN delivery - #58
Merged
Merged
Conversation
…C_URL, kept a week
On S3 a public library answered /v1/files/{key} with a 302 to a 5-minute
pre-signed URL on the bucket's raw endpoint (private, max-age=240), so apps
linking one file by key paid an extra round trip every few minutes and
fetched uncached from R2. It now sends them to the file under PUBLIC_URL,
where /v1/stores already names it and a CDN keeps it: public, max-age=604800
for the standard path, 300 s for a file adopted in place. A private library
still pre-signs; so does a public one whose PUBLIC_URL is its own /files/.
Withdrawn keys stay 410. Spec 1.2 registry API §7 says it is allowed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…COUNTS=off
Staff of a deployment can sign in to their own app instead of the library: the
app's server calls with one key and says who it acts for, and the library's
records name that person.
- auth_api_keys.act_for (migration step 7, additive) and an actors table
(id, name, first_seen_at, last_seen_at); actFor on key records, settable on
create (POST v1/admin/keys, key add --act-for) and by PATCH v1/admin/keys/{id}
(key act-for <id> on|off).
- Chalk-Actor: base64url JSON {id, name}. From an act-for key the caller's
who-value becomes the id, so uploads, adopted files, highlight reviews and
drawn boxes (the body's `by` is replaced) and ?mine=1 all mean the person;
actors are upserted at most once a minute per id and process. Any other
caller gets 403 act_for_not_allowed, a malformed header 400. CORS allows it.
- GET v1/auth/me answers actFor and actingFor; GET v1/admin/actors lists actors.
- HUMAN_ACCOUNTS=off: password and refresh grants are unsupported_grant_type
(and not in discovery), user admin endpoints 404, users' tokens refused, the
user CLI commands refuse; keys and TOKENS keep working.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A deployment can run the server as a login with row rights only: the schema's owner runs `chalk-library migrate` as a release step, and the server (and the key/user CLI) then creates nothing at start and refuses a schema that lacks a migration step it knows, with a message saying what to run. Default stays true. CREATE SCHEMA is now issued only when the schema is missing: Postgres checks the right to create schemas before IF NOT EXISTS, which an owner given its schema by the setup does not have. The runtime-login test makes its own database on a real Postgres (CHALK_LIBRARY_TEST_DB): owner migrates, a DML-only login serves keys, act-for uploads, trigram search, highlights and users. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ser accounts Registry API §10.7 (Chalk-Actor: validation, recording the actor id, 403 for any other caller) and §10.8 (no password or refresh grants, no user endpoints), with actFor, PATCH keys and GET v1/admin/actors in §10.5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntime logins The settings, the migrate release step, the grants for a DML-only runtime login and where pg_trgm goes (the setup creates it in the library's schema). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n own /files/, never for SVG - The redirect to PUBLIC_URL is kept public, max-age=86400 (was a week), so a withdrawal reaches browsers within a day; adopted files stay 300 s. - Whether PUBLIC_URL is a public domain is decided from the address: a /files/ path (the default when PUBLIC_URL is unset, even without SERVER_URL, which redirected to http://localhost:<port>/files/) pre-signs. - An SVG is pre-signed as an attachment (needsAttachment in storage.ts), never sent to a public address that would open it inline. - Tests: libraryFromEnv with PUBLIC_URL and SERVER_URL unset and with an own https://host/files/, the SVG case, an adopted path that needs encoding, and the public library's redirect while an adopted file moves. - Spec §7/§8: how long a withdrawal takes to reach readers, and the CDN purge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ptional sandbox headers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s only after a change
From review of the act-for work:
- a caller not acting for someone may not send a highlight `by` starting with
staff: or system: (400 actor_requires_act_for), so a plain author key or a
bootstrap token cannot sign as a person or a job;
- import keeps the restored links' reviewers, but staff:/system: ones only from
an act-for key or an administrator;
- a bodiless request (DELETE links/{id}) under Chalk-Actor counts as an empty
body, so `by` comes from the header instead of failing with 400;
- actor names are trimmed and refuse Cc controls (C1 included), bidi
embeddings, overrides and isolates, and U+2028/2029;
- the actor is recorded only after a 2xx answer to a non-GET/HEAD request:
reads, refusals and failures leave no row;
- Chalk-Actor is no longer allowed by CORS: an act-for key belongs on a server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… after a change Registry API §10.7 and §11.3: actor_requires_act_for for callers not acting for someone, import keeping original reviewers (act-for key or admin only), names without control or bidi characters, actors recorded after a successful change, and act-for keys never used from a browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… sign in elsewhere A table of the keys (dashboard and library-sync with --act-for, CI and readers without), the settings and the release step; writers that name a person or a job need an act-for key and Chalk-Actor instead of a staff:/system: `by`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
migrate.test.ts (an owner migrates, a DML-only login serves with MIGRATE_ON_START=false) skipped without CHALK_LIBRARY_TEST_DB, so it never ran on a PR. The service moves to postgres:18; the test makes its own database and logins on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only a genuinely empty DELETE may omit JSON. Invalid PATCH, DELETE and bulk removal bodies fail without changing links. Co-Authored-By: Codex <noreply@openai.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lets trusted machine keys attribute library changes to staff or background jobs through an explicit act-for capability. Reserved staff/system identities cannot be supplied by ordinary callers; malformed acting requests fail without changing data. Human accounts can be disabled, and deployments can run migrations separately from restricted runtime connections.
Public libraries can redirect suitable files to an explicitly configured CDN. Own-server/default URLs retain pre-signed delivery, SVG retains attachment handling, and browser cache lifetimes and withdrawal/purge behavior are documented.
Validation completed during the November 11 review:
pnpm checkpassed in both source branches.Includes CI coverage for restricted Postgres runtime credentials. Configure writing keys with act-for before upgrading dashboard/job traffic. CDN rules, runtime credentials, and optional human-login retirement remain operator-controlled release steps; no production migration is executed here.
Companion PRs: