P4.4: bearer auth + write endpoints on distd
distd stops being read-only. http.sx learns the write-side request surface: header capture with case-insensitive lookup, a Content-Length- bounded body read loop (8K header cap, 512 MiB body cap -> 413, 411 for length-less POST/PUT), and the matching status texts. Auth (server/auth.sx): Authorization: Bearer is re-hashed and resolved via find_token_by_hash, then gated through check_token — 401 for missing/malformed/unknown credentials, 403 with a refusal-specific code (auth.revoked/expired/missing_scope/app_forbidden/channel_forbidden); successful auth stamps last_used_at. check_token's app gate now treats an empty REQUEST app like an empty request channel (uploads are app-agnostic until a release references them). Write routes (POST, publish scope): /api/upload content-addresses the body; /api/apps/<slug>/releases publishes over already-uploaded objects through commit_publish — the back half extracted from run_publish so CLI and HTTP publishes share one find/create-app -> transaction -> audit -> persist pipeline; channels/<name>/promote|rollback delegate to the P3.5 CLI pipelines. Reads stay public. make test 17/17 (new: server_write.sx pinned acceptance over curl).
This commit is contained in:
@@ -118,6 +118,12 @@ check_empty_request_channel :: () -> bool {
|
||||
return refusal(scoped_token(), "publish", "acme-app", "", 500) == "";
|
||||
}
|
||||
|
||||
// An empty REQUEST app passes the app gate likewise (an upload is
|
||||
// app-agnostic until a release references it).
|
||||
check_empty_request_app :: () -> bool {
|
||||
return refusal(scoped_token(), "publish", "", "", 500) == "";
|
||||
}
|
||||
|
||||
// An unscoped token (empty app_slug/channel) authorizes any app/channel.
|
||||
check_unscoped_matches_all :: () -> bool {
|
||||
t := scoped_token();
|
||||
@@ -276,6 +282,7 @@ main :: () -> i32 {
|
||||
failures += run_case("check: app scope mismatch refused", check_app_mismatch());
|
||||
failures += run_case("check: channel scope mismatch refused", check_channel_mismatch());
|
||||
failures += run_case("check: empty request channel passes", check_empty_request_channel());
|
||||
failures += run_case("check: empty request app passes", check_empty_request_app());
|
||||
failures += run_case("check: unscoped token matches all", check_unscoped_matches_all());
|
||||
failures += run_case("validate: accepts good tokens", check_validate_accepts());
|
||||
failures += run_case("validate: rejects each bad form", check_validate_rejects());
|
||||
|
||||
Reference in New Issue
Block a user