A signed link is a temporary capability: anyone who obtains it may be able to use that capability until expiry. Agree the object, operation and lifetime before adding a download button to a customer portal. Do not mistake an unguessable URL for user-specific authorisation.
Who should use this acceptance brief
Design studios and B2B customer document portals. Use this as a scoped commissioning task for a website supplier. Where system evidence is required, a teaching file is not a substitute.
Source-bound platform fact
R2 presigned URLs bind an S3 operation and expiry; they use the S3 API endpoint rather than a custom-domain URL. Treat them as bearer-style secrets and review access before issuing them. Cloudflare R2: presigned URLs · Checked 16 October 2026.
Filled teaching example
Synthetic example, not a client case. Inputs, expected decisions and counterexamples follow; no live platform integration is claimed.
On narrow screens, scroll to read the complete table.
| Input / case | Check basis | Expected decision |
|---|---|---|
| GET, file-A, t=90, expiry=100 | matching operation/object | within model window |
| PUT for same link | method mismatch | deny |
| GET at expiry=100 | boundary reached | deny in model |
Run the acceptance exercise
- Document who may request the link and which object that user is authorised to obtain.
- Issue only the required operation for a short justified period; never log the full signature.
- In an authorised test bucket, test wrong-object, wrong-method and expiry paths before delivery.
Interpret the result and retain evidence
The offline checker models a request-start boundary and does not validate cryptographic signatures or implement R2. A real download started before expiry may have different transfer behaviour; verify the storage provider’s current behaviour. If per-user revocation is required, specify an authenticated gateway instead of assuming every signed URL can be individually revoked.
Limits before implementation
No real credentials, bucket policies or customer files are used. The example is not a security certification or production authorisation engine.
Replay the finite example
Save both files in one folder and run with Node22.13 or newer. These finite checks are not a live service or certification. Filled inputs and expected outputs · Inspectable functions
node decision-check.mjs private-download-expiry-contract.json