This page is the historical one-page contract for the implemented S3 / Swift subset on this fleet. The isolation unit is a Keystone project (historical “tenant”), not a single invented customer name. Stance: IMPLEMENTED_SUBSET_ONLY. It is not a drop-in for every S3 client, and it is not a Swift twin.
Scoreboard evidence: post-GUARD
strict-s3-dual-20260818-postguard.json (2026-08-18, SHA-256
52588c82…), failing set identical to post-GATE (50f0c860…). Method:
Dual-oracle. Client behavior: S3 API.
Claim boundary: parity.
为什么以前要填「真正租户」
之前合同页上的「真正租户 / TBD tenant」不是技术上只能开一个账号。
那是法律和 SLO 标签:防止有人把实验室残留(AUTH_dev、AUTH_test、
AUTH_lab)当成客户。
Keystone 里隔离单位是 project(历史上也叫 tenant)。一个用户可以对
多个 project 有角色;一个 project 也可以有多个用户或组。Swift 账号通常
是 AUTH_<project_id>。S3(EC2)凭证按用户发放,经 s3token 落到某个
project。
系统本身已经允许多 project、多用户。本合同写的是:本舰队书面子集覆盖
哪些 Keystone project(可以是一列),以及在这些 project 上有角色的已
认证用户,可以使用已实现的 S3 / Swift 子集。不编造一个强制的唯一客户名。
也不把 AUTH_dev 写成生产用户——它仍是自动化残留。
Binding
| Item | Value |
|---|---|
| Stance | IMPLEMENTED_SUBSET_ONLY |
| Frozen 57-case scoreboard | 49/8 is the acceptance pass (rc=1 is expected) |
| 57/57 zero-fail runner | not a go-live condition |
| Recorded live state (2026-08-18) | Guard 3d0138d5… ×4 + VIP; object 471e8b73… ×4 |
| Binds the VIP | yes, on the Guard generation |
| Isolation unit | Keystone project (Swift account AUTH_<project_id>) |
| In-scope projects | operator-listed project IDs (may be several). No mandatory customer name. Lab leftovers AUTH_dev / AUTH_test / AUTH_lab are out of scope. |
| Who may use the subset | any authenticated user or group with a role on an in-scope project |
| S3 credentials | per-user EC2 keys, scoped through s3token to a project |
Parties
| Role | Value |
|---|---|
| Provider | Peregrine lab fleet (Contabo VIP 10.0.0.10:8085) |
| In-scope Keystone projects | operator lists project IDs; this page does not invent one |
| Principals | users / groups with a role on those projects |
| Allowed clients | TBD — operator fills |
In scope (after Guard)
| Surface | Contract |
|---|---|
| SigV4 header + presign (skew / expiry enforced) | yes |
| SigV2 header + presign | yes |
aws-chunked / STREAMING-AWS4-HMAC-SHA256-PAYLOAD |
yes |
Bucket CRUD, GET / ListBuckets, GetBucketLocation |
yes |
| Object PUT / GET / HEAD / DELETE, copy, Range | yes |
| ListObjects v1 / v2 | yes |
| MPU (initiate, part, list, complete, abort) + composite ETag | yes |
| Versioning, ListVersions, versioned GET/DELETE | yes (cross-proxy CAS binds with Guard) |
| Multi-delete | yes |
| Bucket ACL read/write; object ACL read | yes |
Account-root PUT/DELETE/POST/HEAD / |
405 MethodNotAllowed (supplement B 3/3; AUTH_dev stayed active as leftover evidence, not as a customer) |
| EC | liberasurecode 1.8.0 |
| Consistency daemons | 12/13; swift-account-reaper excluded |
Rust extras (kept)
These stay implemented. They are not turned into 501. They are
not a Python-parity PASS on the frozen 57 (seven of the eight
residuals). Second scoreboard: tools/strict-s3-supplement.py.
| Extra | Rust behavior |
|---|---|
Object ACL write ?acl |
200 |
Bucket tagging write ?tagging |
200 |
Object tagging delete ?tagging |
204 |
| Bucket CORS GET / PUT / DELETE | 200 / 200 / 204 |
RestoreObject ?restore |
honest 400 InvalidObjectState while cold routing is off |
Out of scope
| Surface | Notes |
|---|---|
| Physical cold-tier / storage-policy routing | proxy does not load the map; LocalDir is lab-only, default off |
| Runtime multi-tenant IAM | library only; proxy does not load policies |
?policy ?website ?inventory and other unlisted subresources |
501 NotImplemented |
| Certified object-lock product | lab canary only; not an attested retention product |
| Multi-cluster container-sync | same-cluster unit only |
| KMIP | residual |
| eventlet / greenlet serving | not wired |
| Multi-primary auto-shrink | disabled by default |
swift-account-reaper |
stays frozen |
| Lab leftover accounts | AUTH_dev / AUTH_test / AUTH_lab are not customers; leftover cleanup is evidence, do not silently delete |
Platform
| Item | Contract |
|---|---|
| Intended public name | causalhelix.com (sibling TLS agent). Not a live HTTPS claim. |
| Live client path | lab self-signed VIP https://10.0.0.10:8085 |
| Alerts | mailbox named 74511.lab@gmail.com; channel being connected. Proven sink remains lab JSONL on swift1. |
| Object servers | BUG-1 build 471e8b73… (rolled 2026-08-18). Wave-2 is the rollback copy. |
| DR config-plane backup | lab weekly cron; passphrase stays with the operator |
| HAProxy / Keepalived / VIP | do not restart or move in this contract |
SLO
| Metric | Value |
|---|---|
| Availability | TBD — operator fills |
| PUT / GET / LIST latency | TBD — operator fills |
| Durability target | TBD — operator fills |
| Support hours / on-call | TBD — operator fills |
| Public hostname | intended causalhelix.com; HTTPS not live |
| Alert receiver | 74511.lab@gmail.com — mailbox named, channel being connected |
Rollback
Rollback target is Gate (671bcbaf…) on each node’s
swift-proxy-server.rollback.swiftN.* copy. Recipe:
Runbooks.
Operator fills
| Field | Value |
|---|---|
| In-scope Keystone project IDs | list (may be several); no invented customer name |
| Principals | any authenticated user / group with a role on those projects |
| Allowed clients | TBD — operator fills |
| Availability SLO | TBD — operator fills |
| Latency SLO | TBD — operator fills |
| Durability target | TBD — operator fills |
| Support hours / on-call | TBD — operator fills |
| Public hostname + certificate | intended causalhelix.com; certificate and HTTPS not live |
| Alert receiver | 74511.lab@gmail.com — mailbox named, channel being connected |
| Post-Guard rollback SHA | Gate 671bcbaf2a1d195ad532a00d6132e12b6665486d7117451aa130c5dd603346c9 |