@gradial/aci 0.1.52-rc.29 → 0.1.52-rc.34-e2e.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -0
- package/README.md +4 -4
- package/dist/audience-data-models.d.ts +201 -372
- package/dist/audience-data-models.js +283 -120
- package/dist/cli/compile-registry.mjs +0 -2
- package/dist/collect/aci.js +1 -1
- package/dist/collect/aci.js.sha256 +1 -1
- package/dist/collect/gapbuffer.js +11 -6
- package/dist/internal/platform/collectionstore/errors.d.ts +11 -0
- package/dist/internal/platform/collectionstore/errors.js +20 -0
- package/dist/next/error-pages.d.ts +4 -0
- package/dist/next/error-pages.js +4 -0
- package/dist/next/release-context.d.ts +29 -0
- package/dist/next/release-context.js +55 -0
- package/dist/next/server.d.ts +8 -0
- package/dist/next/server.js +14 -1
- package/dist/react/VideoPlayer.d.ts +1 -1
- package/dist/react/VideoPlayer.js +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +2 -3
- package/dist/testing/conformance/preset.js +3 -0
- package/dist/testing/conformance/root-identity.js +7 -26
- package/dist/testing/conformance/types.d.ts +3 -0
- package/dist/types/image.d.ts +54 -17
- package/dist/types/image.js +102 -18
- package/dist/types/media.d.ts +14 -6
- package/dist/types/video.d.ts +7 -3
- package/migrations/conformance-registry.md +22 -0
- package/package.json +8 -7
- package/src/cli/compile-registry.mjs +0 -2
- package/src/types/image.ts +133 -29
- package/src/types/video.ts +1 -1
- package/templates/astro/starter-content/src/fixtures/sections.ts +0 -1
- package/templates/common/.agents/skills/aci/SKILL.md +4 -3
- package/templates/common/.agents/skills/dam-delivery/SKILL.md +182 -193
- package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +137 -101
- package/templates/common/starter-content/.content/dam/README.md +74 -0
- package/templates/common/starter-content/.content/dam/folders/seed/000000000000000000000000101/governance.json +2 -1
- package/templates/common/starter-content/.content/dam/folders/seed/000000000000000000000000102/governance.json +2 -1
- package/templates/common/starter-content/.content/patterns/components/button.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/container.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/feature_card.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/feature_grid.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/home_hero.json +16 -7
- package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-footer.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-navigation.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/stats_bar.json +2 -2
- package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/layout.tsx +10 -7
- package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
- package/templates/common/.agents/skills/dam-delivery/references/parameter-contract.md +0 -107
|
@@ -1,228 +1,217 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dam-delivery
|
|
3
|
-
description:
|
|
3
|
+
description: Build and use public DAM asset links (`/dam/{assetId}`) with on-the-fly image shaping (resize, crop, format, quality). Use when a page, a CMS field, or an email needs a URL for an approved DAM asset, when choosing between a compiled content link and a shaped public link, when making an asset public or taking it down, or when a `/dam/…` URL answers 301, 403, or 404 unexpectedly.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# DAM Delivery —
|
|
6
|
+
# DAM Delivery — Public Asset Links
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
webp/avif) through signed URLs under `/dam/i/{assetId}/…`. The API mints
|
|
10
|
-
them; clients can neither construct nor alter them — every URL is
|
|
11
|
-
HMAC-signed server-side over a closed, validated parameter contract.
|
|
12
|
-
|
|
13
|
-
## The One Rule: URLs Are Render-Time Artifacts
|
|
14
|
-
|
|
15
|
-
Delivery URLs **expire** (24h maximum by default) and are **banned from
|
|
16
|
-
published payloads**. The publish validator rejects any payload containing
|
|
17
|
-
the `/dam/i/` path marker, exactly as it rejects raw `dam/blobs` pointers.
|
|
18
|
-
|
|
19
|
-
- **DO** mint at render time: SSR handlers, server functions, API-backed
|
|
20
|
-
routes, previews.
|
|
21
|
-
- **DO NOT** bake minted URLs into content JSON, compiled payloads, or
|
|
22
|
-
anything that gets published — a frozen release would carry URLs that
|
|
23
|
-
permanently 404 within a day.
|
|
24
|
-
- For content baked into releases, keep using the pre-baked derivative
|
|
25
|
-
pipeline (`imageSlots` in contracts → `dam/derivatives/…` URLs via
|
|
26
|
-
`imageAttrs()`/`Picture`). Delivery URLs complement it; they do not
|
|
27
|
-
replace it.
|
|
28
|
-
|
|
29
|
-
## Minting
|
|
30
|
-
|
|
31
|
-
One endpoint mints single or batch; the request is always an array of
|
|
32
|
-
parameter sets and one signed URL comes back per set, in order.
|
|
8
|
+
Every approved DAM asset has one public address on the site's own domain:
|
|
33
9
|
|
|
34
10
|
```
|
|
35
|
-
|
|
36
|
-
{
|
|
37
|
-
"requests": [
|
|
38
|
-
{ "width": 800, "height": 600, "fit": "fill", "gravity": "noea",
|
|
39
|
-
"quality": 90, "dpr": 2, "format": "avif" },
|
|
40
|
-
{ "width": 400 }
|
|
41
|
-
]
|
|
42
|
-
}
|
|
11
|
+
https://{site}/dam/{assetId}
|
|
43
12
|
```
|
|
44
13
|
|
|
45
|
-
|
|
14
|
+
Add a query to shape an image on the fly:
|
|
46
15
|
|
|
47
|
-
```json
|
|
48
|
-
{
|
|
49
|
-
"results": [
|
|
50
|
-
{ "url": "/dam/i/ast_…/…", "expiresAt": "2026-08-16T12:00:00Z" },
|
|
51
|
-
{ "error": { "status": 400, "code": "dam.delivery.invalid_param",
|
|
52
|
-
"message": "width must be 1-4096", "details": { "param": "width" } } }
|
|
53
|
-
]
|
|
54
|
-
}
|
|
55
16
|
```
|
|
56
|
-
|
|
57
|
-
Asset-level failures (asset not found, unavailable, permission denied)
|
|
58
|
-
fail the whole request; parameter failures are per-item so one bad set
|
|
59
|
-
cannot sink its siblings. Batches cap at 100 parameter sets.
|
|
60
|
-
|
|
61
|
-
CLI equivalents:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# Single mint from flags
|
|
65
|
-
aci dam delivery-url ast_2E9qL0001aBcDeF --width 800 --height 600 \
|
|
66
|
-
--fit fill --gravity noea --quality 90 --format avif --dpr 2
|
|
67
|
-
|
|
68
|
-
# Batch from a JSON array (prints one URL<TAB>expiresAt line per mint)
|
|
69
|
-
aci dam delivery-url ast_2E9qL0001aBcDeF \
|
|
70
|
-
--params '[{"width":400},{"width":800,"dpr":2}]'
|
|
17
|
+
https://{site}/dam/{assetId}?w=640&h=384&fit=crop&fm=jpg&q=80
|
|
71
18
|
```
|
|
72
19
|
|
|
73
|
-
|
|
20
|
+
The link is built from the asset ID alone. Nothing is minted or signed and
|
|
21
|
+
nothing expires, so the same link can sit in a page, a CMS field, or an
|
|
22
|
+
email for years. It always serves the newest approved public version of
|
|
23
|
+
the asset.
|
|
74
24
|
|
|
75
|
-
|
|
76
|
-
error codes: `references/parameter-contract.md`.
|
|
25
|
+
## Retired — Do Not Use
|
|
77
26
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
| `fit` | `fit` \| `fill` | `fit` | requires `width` or `height` |
|
|
82
|
-
| `gravity` | `ce`, `no`, `so`, `ea`, `we`, `noea`, `nowe`, `soea`, `sowe`, or `fp:{x}:{y}` (x,y ∈ [0,1]) | `ce` | non-default gravity requires `fit: "fill"` |
|
|
83
|
-
| `quality` | 1–100 | 82 | |
|
|
84
|
-
| `dpr` | 1–3 | 1 | multiplies output dimensions |
|
|
85
|
-
| `format` | `webp` \| `avif` \| `jpeg` \| `png` | `webp` | becomes the URL extension |
|
|
86
|
-
|
|
87
|
-
Special cases:
|
|
88
|
-
|
|
89
|
-
- **SVG** is passthrough-only: only the empty parameter set `{}` is
|
|
90
|
-
accepted; any transform param is rejected.
|
|
91
|
-
- **Non-image assets** are never served through `/dam/i/*`; use the
|
|
92
|
-
download endpoints instead.
|
|
93
|
-
- Oversized blobs (over the origin's 200 MB streaming envelope) refuse to
|
|
94
|
-
mint with `dam.delivery.source_too_large`.
|
|
95
|
-
|
|
96
|
-
## Expiry Semantics
|
|
97
|
-
|
|
98
|
-
- Every URL carries a signed expiry; `expiresAt` in the response is that
|
|
99
|
-
instant. After it, the URL 404s at the origin and cached copies die at
|
|
100
|
-
the CDN.
|
|
101
|
-
- The bound is quantized (default 1h): identical requests minted within
|
|
102
|
-
the same quantum return **byte-equal URLs**, so re-minting per render is
|
|
103
|
-
cheap and cache-friendly. Effective lifetime is between `maxTTL − 1h`
|
|
104
|
-
and `maxTTL` (default 24h).
|
|
105
|
-
- A version whose scheduled expiry revokes delivery gets URLs that expire
|
|
106
|
-
exactly at that boundary, which may be much sooner. Never assume a
|
|
107
|
-
fixed TTL — read `expiresAt`.
|
|
108
|
-
- Re-mint instead of caching URLs long-term. Caching a minted URL for the
|
|
109
|
-
duration of one render/request is fine.
|
|
110
|
-
|
|
111
|
-
## Availability: Why Mints Get Denied
|
|
112
|
-
|
|
113
|
-
Minting serves **only the latest approved, publishable version** and fails
|
|
114
|
-
closed. Expect typed errors (HTTP 422 unless noted):
|
|
115
|
-
|
|
116
|
-
| Code | Meaning |
|
|
117
|
-
| --- | --- |
|
|
118
|
-
| `dam.asset.no_approved_version` | draft-only, embargoed, expired, or usage-restricted versions — nothing publishable |
|
|
119
|
-
| `dam.asset.not_active` | archived or deleted |
|
|
120
|
-
| `dam.asset.legal_hold` | under legal hold |
|
|
121
|
-
| `dam.asset.blocked` | asset-wide publication block (usage restriction) |
|
|
122
|
-
| `dam.permission_denied` | caller lacks download permission (403) |
|
|
123
|
-
| `dam.delivery.not_image` | non-image MIME |
|
|
124
|
-
|
|
125
|
-
There is no fallback to unapproved versions anywhere. Approval changes URL
|
|
126
|
-
identity (new blob → new URLs on next mint); already-minted URLs keep
|
|
127
|
-
serving what they named until they expire.
|
|
27
|
+
Earlier SDK releases documented two delivery lanes that no longer exist.
|
|
28
|
+
If you meet any of these in old content, notes, or code, replace them with
|
|
29
|
+
the link above. They are not served and they do not redirect.
|
|
128
30
|
|
|
129
|
-
|
|
31
|
+
| Retired | Now |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| Signed URLs under `/dam/i/…`, `POST /v1/dam/assets/{assetId}/delivery-urls`, `aci dam delivery-url` | Build `/dam/{assetId}?…` yourself; there is nothing to mint |
|
|
34
|
+
| Permalinks under `/dam/a/…`, `GET /v1/dam/assets/{assetId}/permalinks`, recipe URLs | `/dam/{assetId}?…` |
|
|
35
|
+
| The `lifecycle.publicDelivery` flag | Approving a version makes it public (see below) |
|
|
36
|
+
| `width`, `height`, `gravity`, `dpr`, `quality`, `format` | `w`, `h`, `fit`, `fm`, `q` |
|
|
130
37
|
|
|
131
|
-
|
|
132
|
-
public URL** — Sanity-style, deterministic from the assetId alone, no mint
|
|
133
|
-
API in the loop:
|
|
38
|
+
## The Link
|
|
134
39
|
|
|
135
40
|
```
|
|
136
|
-
|
|
41
|
+
/dam/{assetId}[/{slug}][?w=…&h=…&fit=…&fm=…&q=…]
|
|
137
42
|
```
|
|
138
43
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
the
|
|
148
|
-
|
|
44
|
+
- **`assetId`** is a raw 27-character ID made of digits and letters
|
|
45
|
+
(`0-9A-Za-z`), with no prefix. IDs that start with `ast_` are retired
|
|
46
|
+
and rejected; per ADR 0043 they are replaced by the breaking migration,
|
|
47
|
+
with no compatibility period.
|
|
48
|
+
- **`slug`** is optional and cosmetic: `/dam/{assetId}/spring-sale.jpg`
|
|
49
|
+
answers with a permanent redirect to `/dam/{assetId}`, keeping the query.
|
|
50
|
+
Use it when a tool insists on a URL that ends in a file extension. The
|
|
51
|
+
slug is never checked against anything, and its extension does not pick
|
|
52
|
+
the format.
|
|
53
|
+
- The CLI prints the path for an ID. It is a formatter only: it makes no
|
|
54
|
+
API call and does not tell you whether the asset is public.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
aci dam permalink 2E9qL0001aBcDeFgHiJkLmNoPqR
|
|
58
|
+
# /dam/2E9qL0001aBcDeFgHiJkLmNoPqR
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The route is served by the deployed site's hosting edge. The site's own
|
|
62
|
+
dev server (`npm run dev`) serves `/dam/…` links for assets seeded in the
|
|
63
|
+
local `.content/dam/` tree; anything else answers 404 there — test it
|
|
64
|
+
against the deployed domain.
|
|
65
|
+
|
|
66
|
+
## Shaping an Image
|
|
67
|
+
|
|
68
|
+
Five query parameters, and only these. Full rules and worked examples:
|
|
149
69
|
`references/permalink-grammar.md`.
|
|
150
70
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
71
|
+
| Param | Values | Default | Notes |
|
|
72
|
+
| --- | --- | --- | --- |
|
|
73
|
+
| `w`, `h` | whole numbers | none | 1–4096, honored exactly — no snapping or size ladder |
|
|
74
|
+
| `fit` | `max` \| `crop` | `max` | `max` fits inside the box; `crop` fills it and needs both `w` and `h` |
|
|
75
|
+
| `fm` | `webp` \| `avif` \| `jpg` \| `png` | `webp` | the format is always this parameter, never the browser's `Accept` header |
|
|
76
|
+
| `q` | 5–100 | 80 | snapped down to steps of 5 |
|
|
77
|
+
|
|
78
|
+
Three things to know before writing a link:
|
|
79
|
+
|
|
80
|
+
- **Any one parameter turns shaping on, and the rest take their
|
|
81
|
+
defaults.** `?w=640` serves WebP at quality 80, not the original format.
|
|
82
|
+
To keep a JPEG a JPEG, say `fm=jpg`.
|
|
83
|
+
- **No parameters means the original.** `/dam/{assetId}` streams the
|
|
84
|
+
approved file byte for byte.
|
|
85
|
+
- **Nothing is rejected.** Unknown parameter names (`utm_*`, `mkt_tok`,
|
|
86
|
+
cache busters) are dropped. Out-of-range or unrecognised values are
|
|
87
|
+
snapped to an allowed one, sizes and quality always downward: `w=333`
|
|
88
|
+
serves 256, `q=77` serves 75, `fm=gif` serves WebP. Do not expect
|
|
89
|
+
pixel-exact sizes off the ladder. A `w`, `h`, or `q` that is not a
|
|
90
|
+
whole number (`w=abc`, `q=high`) is treated as if it had been left out,
|
|
91
|
+
so a typo never shrinks an image or lowers its quality.
|
|
92
|
+
|
|
93
|
+
The edge settles every link on one canonical form: the parameters in the
|
|
94
|
+
order `w`, `h`, `fit`, `fm`, `q`, after snapping, with `fit`, `fm`, and
|
|
95
|
+
`q` always present. A link written any other way still works. A request
|
|
96
|
+
already on `/dam/{assetId}` with a noncanonical query is answered with one
|
|
97
|
+
permanent redirect to the canonical link (sites hosted on CloudFront tidy
|
|
98
|
+
the query without a visible redirect). A request carrying a slug and a
|
|
99
|
+
noncanonical query can redirect twice: once to drop the slug, once to
|
|
100
|
+
canonicalize the query. Write the canonical form when you control the URL
|
|
101
|
+
and you skip those hops.
|
|
102
|
+
|
|
103
|
+
Shaping only applies to JPEG, PNG, WebP, and AVIF originals. Everything
|
|
104
|
+
else, SVG included, is served only as a file download, never displayed
|
|
105
|
+
inline. On AWS CloudFront this holds only once the hosting fix (PR #709)
|
|
106
|
+
has rolled out to the tenant; until then that lane may serve SVG or HTML
|
|
107
|
+
inline. See the reference for the size limits.
|
|
108
|
+
|
|
109
|
+
## What Makes a Link Serve
|
|
110
|
+
|
|
111
|
+
Approving a version is the "make public" act. There is no separate flag.
|
|
160
112
|
|
|
161
113
|
```
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
Returns the base permalink and per-recipe URLs (path + absolute URL), the
|
|
166
|
-
grammar constants (width ladder, quality step, defaults), the
|
|
167
|
-
`publicDelivery` flag state, and a `warning` field (below). CLI:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
aci dam permalink ast_2E9qL0001aBcDeF # base URL
|
|
171
|
-
aci dam permalink ast_2E9qL0001aBcDeF --recipe email-hero
|
|
114
|
+
POST /v1/dam/assets/{assetId}/lifecycle
|
|
115
|
+
{ "action": "approve", "versionId": "…", "expectedHead": "…" }
|
|
172
116
|
```
|
|
173
117
|
|
|
174
|
-
|
|
175
|
-
the flag is flipped — check `publicDelivery` to know whether it resolves.
|
|
118
|
+
Read `effects` in the response to see what happened:
|
|
176
119
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
`
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
the
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
120
|
+
| Effect | Meaning |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `live_published` | the link now serves this version |
|
|
123
|
+
| `public_admission_vetoed:<cause>` | the version is approved but **not public**: it carries an expiry date, an embargo still in force, a usage block, or a license that does not allow publication. The link keeps serving the previous public version, if there is one |
|
|
124
|
+
| `live_plane_unconfigured` | a local or dev stack with no delivery wired; nothing was made public |
|
|
125
|
+
|
|
126
|
+
On the asset record (`GET /v1/dam/assets/{assetId}`), a public version
|
|
127
|
+
shows `deliveryTier: "public"` in its governance, and a refused one shows
|
|
128
|
+
`tierAdmissionVeto`.
|
|
129
|
+
|
|
130
|
+
- **A newer approved version takes over the same link.** Nothing needs
|
|
131
|
+
re-pasting.
|
|
132
|
+
- **To take a link down**, `demote` the version (the link falls back to
|
|
133
|
+
the previous public version, or stops serving if there is none) or
|
|
134
|
+
`archive` the asset. Both use the same lifecycle endpoint.
|
|
135
|
+
- **Governance that would have blocked the approval cannot be added while
|
|
136
|
+
a version is public.** A patch adding an expiry date, an embargo, a
|
|
137
|
+
usage block, or a license without publication is refused with a
|
|
138
|
+
conflict that tells you to demote first.
|
|
139
|
+
- **Changes take up to five minutes to show everywhere.** Responses are
|
|
140
|
+
`Cache-Control: public, max-age=300`, so a new version or a take-down
|
|
141
|
+
can lag by that long in browsers and CDN caches. On AWS CloudFront,
|
|
142
|
+
cached copies can currently outlive that window — the image pipeline
|
|
143
|
+
sets a one-year TTL and the distribution permits it — until the hosting
|
|
144
|
+
lane is corrected; the five minutes holds for Vercel and Cloudflare. Do
|
|
145
|
+
not treat a public link as instantly revocable, and do not re-cache it
|
|
146
|
+
for longer downstream.
|
|
147
|
+
|
|
148
|
+
## Compiled Content Link or a Public Link?
|
|
149
|
+
|
|
150
|
+
- **Images a page renders from content: use the compiled live link.**
|
|
151
|
+
Author a `dam.assetRef` (asset id + alt); the compiler emits the
|
|
152
|
+
versionless permalink and the SDK asset component builds the `srcset`
|
|
153
|
+
from the slot's declared widths at render time. Declare `imageSlots` in
|
|
154
|
+
the contract and render with `imageAttrs()` or `Picture`; you never
|
|
155
|
+
construct a URL. There is no pre-baked derivative pipeline — publish
|
|
156
|
+
stages no asset bytes.
|
|
157
|
+
- **A URL that lives outside the build: use the public link.** A field in
|
|
158
|
+
an external CMS, an email, a social card, a partner page, or a one-off
|
|
159
|
+
size that no slot declares.
|
|
160
|
+
|
|
161
|
+
The difference that matters: a compiled link follows approval and take-down
|
|
162
|
+
through each publish, while a public link follows them on its own, within
|
|
163
|
+
the five-minute window.
|
|
164
|
+
|
|
165
|
+
Published content may carry `/dam/{assetId}` links. The publish check
|
|
166
|
+
rejects a payload that contains a raw source path (`dam/blobs/…`) or a
|
|
167
|
+
retired `/dam/a/` or `/dam/i/` path.
|
|
168
|
+
|
|
169
|
+
## Email and External CMS Fields
|
|
170
|
+
|
|
171
|
+
1. **Paste the link; never let the tool import the bytes.** Many email
|
|
172
|
+
tools offer to "import" or "copy" images to their own CDN. Refuse. An
|
|
173
|
+
imported copy escapes approval and take-down forever; the link is the
|
|
174
|
+
governed pointer.
|
|
175
|
+
2. **Always set `fm=jpg` or `fm=png` in email.** The default is WebP, and
|
|
176
|
+
Outlook desktop cannot render WebP.
|
|
177
|
+
3. **Use the slug form when a tool wants a file extension:**
|
|
178
|
+
`/dam/{assetId}/spring-sale.jpg?w=640&fm=jpg`.
|
|
179
|
+
4. **`block_new_usage` does not take a public link down.** The link cannot
|
|
180
|
+
tell an old placement from a new one, so an asset under that
|
|
181
|
+
restriction keeps serving where it is already pasted. To stop serving,
|
|
182
|
+
demote or archive.
|
|
183
|
+
|
|
184
|
+
## When a Link Does Not Serve
|
|
185
|
+
|
|
186
|
+
Errors are never cached (`no-store`) on Vercel and Cloudflare. On AWS
|
|
187
|
+
CloudFront, 403 and 5xx responses may be cached by the distribution for up
|
|
188
|
+
to about ten seconds regardless of `no-store`. Exact codes differ slightly
|
|
189
|
+
between hosting providers, so treat any 4xx as "not served".
|
|
190
|
+
|
|
191
|
+
| You see | Why | Do |
|
|
192
|
+
| --- | --- | --- |
|
|
193
|
+
| 301 | a slug was dropped or the query was put in canonical form | follow it; write the canonical link next time |
|
|
194
|
+
| 403 | the asset has no public version (never approved, approval vetoed, demoted, archived, or expired), or the ID is malformed | check `effects` from the approve call and `deliveryTier` on the asset record |
|
|
195
|
+
| 404 | a retired `/dam/a/…` or `/dam/i/…` path, DAM delivery is not enabled for this site, or you are on the local dev server | rewrite the link; ask the operator to enable DAM delivery |
|
|
196
|
+
| 413 | the original is too large to shape | drop the query to get the original, or upload a smaller master |
|
|
197
|
+
| 415 | shaping was asked of a non-image original | drop the query |
|
|
198
|
+
| 503 | delivery could not read its own state and refused rather than guess | retry; if it persists, it is an operator issue |
|
|
199
|
+
| A download instead of an image | the original is not JPEG, PNG, WebP, or AVIF | by design; render SVGs through the site's own image pipeline |
|
|
215
200
|
|
|
216
201
|
## Draft Previews (Management Surfaces Only)
|
|
217
202
|
|
|
218
|
-
|
|
219
|
-
|
|
203
|
+
The public link never serves a draft. A draft or rejected version is
|
|
204
|
+
reachable only by an authenticated caller with read permission on the
|
|
205
|
+
asset, and only by naming the exact version:
|
|
220
206
|
|
|
221
207
|
```
|
|
222
|
-
GET /v1/dam/assets/{assetId}/versions/{versionId}/preview
|
|
223
|
-
GET /v1/dam/assets/{assetId}/versions/{versionId}/download
|
|
208
|
+
GET /v1/dam/assets/{assetId}/versions/{versionId}/preview
|
|
224
209
|
```
|
|
225
210
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
211
|
+
It answers `302` to a short-lived signed URL: for JPEG, PNG, GIF, and WebP
|
|
212
|
+
up to 20 MiB, a WebP of that version downsampled at upload (longest edge
|
|
213
|
+
1024 px, never upscaled); for SVG, formats the server does not decode
|
|
214
|
+
(HEIC, AVIF, TIFF, BMP), or a version whose preview is not generated yet,
|
|
215
|
+
the original. Follow the redirect without forwarding your bearer token. It
|
|
216
|
+
takes no shaping parameters. Use it for editorial UIs and thumbnails,
|
|
217
|
+
never for site rendering.
|