منبع حقیقت، محتوا، انتشار و رسانه · فصل ۵ — Vault، Transfer و Provenance Round-trip · 172
Presigned Artifact Transfer
Design a presigned artifact-transfer contract that separates grant creation from artifact identity, binds operation/resource/expiry and expected content evidence, treats possession of the signed URL as sensitive capability state, and closes transfer only after recipient-side digest/size verification rather than URL issuance or HTTP success alone. میتواند «Presigned Artifact Transfer» را در یک pipeline محدود با provenance، rights/version و publication gate تعریف کند.
Lesson summary
Design a presigned artifact-transfer contract that separates grant creation from artifact identity, binds operation/resource/expiry and expected content evidence, treats possession of the signed URL as sensitive capability state, and closes transfer only after recipient-side digest/size verification rather than URL issuance or HTTP success alone.
میتواند «Presigned Artifact Transfer» را در یک pipeline محدود با provenance، rights/version و publication gate تعریف کند.
This lesson produces
میتواند «Presigned Artifact Transfer» را در یک pipeline محدود با provenance، rights/version و publication gate تعریف کند.
Who it is for
Foundation
Use a guided lesson-specific evidence matrix and one worked negative case.
Repair
Re-run only the failed owned dimension with a smaller deterministic synthetic fixture.
Experienced
Start from mixed authority/policy/evidence records; require explicit trade-offs and provenance.
Prerequisites
1. The problem: a signed URL is not just a file link
Assume a reviewer needs artifact ART-77 for twenty minutes. The service creates a GET signed URL, writes the full URL into a debug log, omits the expected digest, and signs with temporary credentials that expire in eight minutes. Saying “a 20-minute link was created” collapses three different things: an access capability, artifact identity, and proof of the bytes received. CON-020 separates them.
2. The owned CON-020 boundary
This lesson owns the presigned grant and receipt-verification boundary. Retention and durability belong to CON-019; human handoff and provenance round-trip belong to CON-021. We do not redesign vault retention, infer a recipient's human identity from a URL, or call HTTP 2xx sufficient completion.
3. Separate the grant from artifact identity
A transfer record must describe both the expected artifact and the access capability. artifact_id, expected_digest, and expected_size bind content expectation; operation, http_method, resource_locator, object_key, signer scope, and expiry bind the authorized request shape. A URL is not itself the artifact digest.
4. Treat the signed URL as a sensitive capability
Google Cloud Storage describes a signed URL as time-limited access to a specific resource and notes that anyone possessing an active URL can perform the allowed request even without an account. MAKNOW therefore treats the complete URL as capability-secret state: do not copy it into ordinary logs, tickets, analytics, or screenshots. Audit data should keep only the necessary redacted/fingerprinted representation.
5. Method and resource are part of the contract
Do not treat a GET grant as generic object permission. The request must match the expected operation, HTTP method, and resource/object key. If the workflow changes to PUT, mint a new grant for that request shape. A GET grant used as if it authorized PUT is a binding failure even when the object name is unchanged.
6. Signed headers and Content-Type matter
Uploads may bind signed headers or a content-type value into the canonical request. A client cannot silently omit a required header or send a different value and then treat the resulting failure as generic storage trouble. Record signed_headers and content_type_constraint so the mismatch is inspectable.
7. Nominal expiry is not always effective validity
Amazon S3 documents that a presigned URL created with temporary credentials cannot remain valid beyond those credentials, and revoked/deleted/deactivated credentials can end validity before the configured URL expiration. Keep expires_at distinct from effective_valid_until. If the signer credential expires in eight minutes, do not promise twenty minutes of effective access.
8. Capability rotation changes state
When a signing key or credential is rotated or revoked, the old grant needs a typed INVALIDATED state. Minting a replacement grant must not leave the old URL represented as valid in workflow state. Audit records should keep grant creation and invalidation separate and bind each request to a specific grant.
9. Bind expected digest and size before transfer
When the expected artifact is known, record expected_digest and expected_size before download/upload. Without them the receiver cannot prove that the arriving bytes are the intended artifact. A filename, object key, or HTTP 200 cannot substitute for content evidence.
10. What RFC 9530 proves—and does not
RFC 9530 defines Content-Digest and Repr-Digest as integrity fields for HTTP content or representations and explicitly does not define authentication, authorization, or privacy. Digest evidence can support integrity; it does not prove the human recipient, rights, approval, or publication fitness.
11. Separate transport success from verification
request_completed_at and http_result=200/2xx show a transport result for a request. State must not jump directly from 2xx to VERIFIED. The receiver must obtain or compute received_digest and received_size and compare them with the expectation. A mismatch is FAIL/BLOCK even when the HTTP request succeeded.
12. A receipt creates auditable closure
A receipt_id binds the specific grant, artifact expectation, transport result, and verification result. A useful receipt lets an auditor determine which bytes moved under which grant and how the receiver validated them. A receipt without content verification cannot support a completion state stronger than UNVERIFIED.
13. Preserve typed non-success states
EXPIRED, INVALIDATED, LEAKED, UNBOUND, FAILED, UNVERIFIED, DEFER, and BLOCK represent different failures. A leaked URL with matching bytes is a capability-security problem; a digest mismatch with a secret-safe URL is an integrity failure; a missing expected digest is an evidence gap. One generic green status destroys these distinctions.
14. Lab: Presigned Transfer Grant & Receipt Verification Record v1
lab://CON-020/CON020-LAB1 contains eight synthetic fixtures: a valid baseline, credential expiry before nominal URL expiry, a leaked URL, HTTP 2xx with wrong bytes, missing expected digest, method mismatch, signed-header/content-type mismatch, and a GET-to-PUT rotation scenario. Each case yields eight evidence/state outputs; the hidden evaluator contains 64 deterministic assertions.
15. Transfer: switch GET to PUT, invalidate the old grant, verify the receipt
The transfer challenge sends a replacement artifact with PUT. Bind content type and expected digest, rotate signing credentials before nominal expiry, and make the old GET grant unusable. A successful PUT still remains UNVERIFIED until the receiver verifies the stored object's digest and size. “Upload succeeded” and “expected artifact verified” are deliberately separate claims.
Official sources and claim boundary
- Google Cloud Storage — Signed URLs:
https://docs.cloud.google.com/storage/docs/access-control/signed-urls - Amazon S3 — Presigned URLs:
https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html - RFC 9530 — Digest Fields:
https://www.rfc-editor.org/rfc/rfc9530.html
K1–K3 are sourced facts rechecked on 2026-09-17. K4 — requiring receipt-side digest/size verification before MAKNOW marks a transfer VERIFIED — is a MAKNOW design rule, not a requirement attributed to Google, AWS, or RFC 9530.
Assessment
There is no answer key in this lesson pack; answer it yourself and mark honestly. "Needs review" sends the lesson to your review queue.
CON-020-Q1 boundary
Why must a presigned URL grant be represented separately from the expected artifact identity?
CON-020-Q2 application
A URL has a nominal 20-minute expiry but its temporary signing credential expires in 8 minutes. What validity may the transfer record claim?
CON-020-Q3 diagnosis
HTTP 200 returns bytes whose digest differs from the expected artifact. Which state must remain non-success and why?
CON-020-Q4 security
The transfer succeeds but the full signed URL was written to an ordinary debug log. What evidence/decision changes?
CON-020-Q5 transfer
Rebuild the contract when GET becomes PUT, Content-Type is constrained, signer credentials rotate, and stored-object verification has not yet completed.
Assessment rubric
A sufficient artifact:
- separates artifact identity/evidence from the presigned grant;
- binds operation, HTTP method, resource/object key, nominal expiry and effective credential validity;
- treats the complete signed URL as sensitive capability state and records a redaction rule;
- records signed-header/content-type/checksum constraints when present;
- preserves credential expiry/revocation/rotation as typed invalidation rather than overclaiming URL lifetime;
- separates HTTP transport result from digest/size verification;
- blocks or defers when expected digest is missing, bytes mismatch, request shape is unbound, or capability secrecy is violated;
- identifies Google/AWS/RFC facts separately from MAKNOW's transfer state-machine design;
- rebuilds the changed GET→PUT context without copying the first decision.
References & freshness
Case studies
Lesson visuals
Lab files
Run python run_checks.py for learner-visible structural checks. Implement or inspect starter.py so each fixture yields explicit grant/request/transport/verification states. Fixtures are synthetic; no URLs are live, no credentials exist, and no network call is required.
The learner task is to keep eight dimensions separate: effective validity, grant state, capability-secret state, request binding, transport state, verification state, receipt state, and bounded decision. Never infer VERIFIED from URL issuance or HTTP 2xx.