@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +4 -4
  3. package/dist/audience-data-models.d.ts +201 -372
  4. package/dist/audience-data-models.js +283 -120
  5. package/dist/cli/compile-registry.mjs +0 -2
  6. package/dist/collect/aci.js +1 -1
  7. package/dist/collect/aci.js.sha256 +1 -1
  8. package/dist/collect/gapbuffer.js +11 -6
  9. package/dist/internal/platform/collectionstore/errors.d.ts +11 -0
  10. package/dist/internal/platform/collectionstore/errors.js +20 -0
  11. package/dist/next/error-pages.d.ts +4 -0
  12. package/dist/next/error-pages.js +4 -0
  13. package/dist/next/release-context.d.ts +29 -0
  14. package/dist/next/release-context.js +55 -0
  15. package/dist/next/server.d.ts +8 -0
  16. package/dist/next/server.js +14 -1
  17. package/dist/react/VideoPlayer.d.ts +1 -1
  18. package/dist/react/VideoPlayer.js +2 -2
  19. package/dist/react/index.d.ts +2 -2
  20. package/dist/react/index.js +2 -3
  21. package/dist/testing/conformance/preset.js +3 -0
  22. package/dist/testing/conformance/root-identity.js +7 -26
  23. package/dist/testing/conformance/types.d.ts +3 -0
  24. package/dist/types/image.d.ts +54 -17
  25. package/dist/types/image.js +102 -18
  26. package/dist/types/media.d.ts +14 -6
  27. package/dist/types/video.d.ts +7 -3
  28. package/migrations/conformance-registry.md +22 -0
  29. package/package.json +8 -7
  30. package/src/cli/compile-registry.mjs +0 -2
  31. package/src/types/image.ts +133 -29
  32. package/src/types/video.ts +1 -1
  33. package/templates/astro/starter-content/src/fixtures/sections.ts +0 -1
  34. package/templates/common/.agents/skills/aci/SKILL.md +4 -3
  35. package/templates/common/.agents/skills/dam-delivery/SKILL.md +182 -193
  36. package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +137 -101
  37. package/templates/common/starter-content/.content/dam/README.md +74 -0
  38. package/templates/common/starter-content/.content/dam/folders/seed/000000000000000000000000101/governance.json +2 -1
  39. package/templates/common/starter-content/.content/dam/folders/seed/000000000000000000000000102/governance.json +2 -1
  40. package/templates/common/starter-content/.content/patterns/components/button.json +2 -2
  41. package/templates/common/starter-content/.content/patterns/components/container.json +2 -2
  42. package/templates/common/starter-content/.content/patterns/components/feature_card.json +2 -2
  43. package/templates/common/starter-content/.content/patterns/components/feature_grid.json +2 -2
  44. package/templates/common/starter-content/.content/patterns/components/home_hero.json +16 -7
  45. package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +2 -2
  46. package/templates/common/starter-content/.content/patterns/components/site-footer.json +2 -2
  47. package/templates/common/starter-content/.content/patterns/components/site-navigation.json +2 -2
  48. package/templates/common/starter-content/.content/patterns/components/stats_bar.json +2 -2
  49. package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
  50. package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
  51. package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
  52. package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
  53. package/templates/nextjs/template/src/app/layout.tsx +10 -7
  54. package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
  55. package/templates/common/.agents/skills/dam-delivery/references/parameter-contract.md +0 -107
@@ -1,131 +1,167 @@
1
- # Public Permalink Grammar Reference (`/dam/a/*`)
1
+ # Public Link Grammar Reference (`/dam/{assetId}`)
2
2
 
3
- The public permanent URL for an asset:
3
+ The one public address for a DAM asset:
4
4
 
5
5
  ```
6
- /dam/a/{assetId}[/{slug-or-recipe}[.{ext}]]?w=400&h=300&fit=crop&fm=jpg&q=80
6
+ /dam/{assetId}[/{slug}]?w=640&h=384&fit=crop&fm=jpg&q=80
7
7
  ```
8
8
 
9
- (The query above shows the *shape* only — `w=400`/`h=300` are off-ladder
10
- and would serve 384x256 after snapping. The recommended examples below
11
- sit exactly on rungs; pick rung values when you control the URL.)
9
+ Permanent, built from the asset ID alone, and always serving the newest
10
+ approved public version. Everything below is enforced at the hosting edge.
11
+ No API call sits in the path of a view, and no API hands these links out —
12
+ you write them.
12
13
 
13
- Permanent, deterministic from the assetId alone, resolving to the current
14
- approved version while the asset is flagged `publicDelivery` and available
15
- for delivery. Everything below is edge-enforced; the API is never in the
16
- per-view path. The grammar constants (ladder, steps, defaults) are also
17
- served machine-readably by `GET /v1/dam/assets/{assetId}/permalinks`.
14
+ ## Asset ID
18
15
 
19
- ## Parameters (open but quantized)
16
+ Exactly 27 characters from `0-9A-Za-z`, no prefix. IDs that start with
17
+ `ast_` are retired and refused; per ADR 0043 the migration to the new IDs
18
+ is breaking, with no compatibility period. Anything else is refused.
20
19
 
21
- Names are Sanity-compatible. Unknown parameter *names* are stripped —
22
- never errors — so ESP tracking decorations (`utm_*`, `mkt_tok`) cannot
23
- break an image. Invalid *values* of these contract params are a 400.
20
+ ## Parameters
24
21
 
25
- | Param | Values | Default | Quantization |
26
- | --- | --- | --- | --- |
27
- | `w`, `h` | positive integers | none | snapped DOWN to the ladder `16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840`; below 16 snaps up to 16, above 3840 down to 3840 |
28
- | `fit` | `crop` \| `max` | `max` | `crop` requires **both** `w` and `h` |
29
- | `fm` | `webp` \| `avif` \| `jpg` \| `png` | `webp` | — |
30
- | `q` | 1–100 | absent → renders at 82 | snapped DOWN to steps of 5; below 5 snaps up to 5; an explicit `q=80` serves 80, never the default — explicit quality is honored after snapping, not silently inflated |
22
+ Only these five names mean anything. Every other name is dropped, so
23
+ tracking decorations (`utm_*`, `mkt_tok`) cannot break an image.
31
24
 
32
- The ladder is the Next.js image `srcset` ladder verbatim, so breakpoints
33
- authored against any modern framework land on rungs instead of snapping
34
- visibly. Quantization is deliberate abuse control: it bounds the
35
- transform cache keyspace per asset.
25
+ | Param | Values | Default | Snapping |
26
+ | --- | --- | --- | --- |
27
+ | `w`, `h` | whole numbers | none | below 16 becomes 16, above 3840 becomes 3840, otherwise snapped DOWN to the ladder `16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840` |
28
+ | `fit` | `max` \| `crop` | `max` | any other value becomes `max` |
29
+ | `fm` | `webp` \| `avif` \| `jpg` \| `png` | `webp` | any other value becomes `webp` |
30
+ | `q` | whole numbers | 80 | below 5 becomes 5, above 100 becomes 100, otherwise snapped DOWN to a step of 5 |
31
+
32
+ Nothing in the query is ever answered with an error. A value the address
33
+ cannot read is treated as if that parameter had been left out, so a typo
34
+ never shrinks an image or lowers its quality. The reading rules are the
35
+ same on every hosting provider:
36
+
37
+ - **Any of the five names turns shaping on**, whatever its value, even an
38
+ empty one (`?w=`).
39
+ - **`w`, `h`, and `q` are read only as a whole number in plain digits**,
40
+ with an optional leading minus sign. Zero and negative numbers count as
41
+ below the minimum (`w=-1` serves 16, `q=0` serves 5). Anything else is
42
+ read as left out: an empty value, letters (`w=abc`, `w=640px`), a
43
+ decimal point (`w=640.7`), an exponent (`w=1e3`), a plus sign, spaces,
44
+ or a number larger in size than 9007199254740991. A `w` or `h` read as
45
+ left out sets no size; a `q` read as left out is 80.
46
+ - **An unrecognised or empty `fit` or `fm` takes its default** (`max`,
47
+ `webp`).
48
+ - **Names, and the values of `fit` and `fm`, are lowercase only.** `W=640`
49
+ is an unknown name and is dropped; `fm=JPG` serves WebP.
50
+ - **When a name repeats, the first one decides**, even when it cannot be
51
+ read: `?w=abc&w=640` sets no width.
52
+
53
+ The ladder is the Next.js image `srcset` ladder, so breakpoints written
54
+ for any modern framework land on a rung instead of snapping visibly.
55
+ Snapping is deliberate: it keeps the number of distinct renditions per
56
+ asset small and bounded.
57
+
58
+ How `fit` behaves:
59
+
60
+ - **`max`** scales the image to fit inside `w` × `h`, keeps its
61
+ proportions, and never crops. Give one dimension and the other follows.
62
+ - **`crop`** scales and crops to fill `w` × `h` exactly. With only one
63
+ dimension there is nothing to crop to, so it behaves like `max`.
64
+ - Neither enlarges: asking for more pixels than the original has serves
65
+ the original size.
36
66
 
37
67
  Deliberately **not** in the grammar:
38
68
 
39
- - No `dpr` — pick the right `w` rung instead (the ladder already covers
40
- device densities the way `srcset` consumes them).
41
- - No `Accept`-header format negotiation — format is always the explicit
42
- `fm`. For email use `fm=jpg` or `fm=png` (Outlook desktop has no WebP).
43
- - `crop=focal` is reserved, not shipped.
69
+ - No `dpr`. Pick a larger `w` rung instead, the way `srcset` does.
70
+ - No crop position or focal point.
71
+ - No format negotiation from the browser's `Accept` header. The format is
72
+ always the explicit `fm`.
73
+ - No recipes or named presets, no signatures, no expiry.
44
74
 
45
- ## Canonical Form, Slugs, and Recipes
75
+ ## Canonical Form
46
76
 
47
- The canonical URL is **extension-less**: `/dam/a/{assetId}?…`. The
48
- optional second path segment (extension stripped) is either:
77
+ One spelling per rendition: `w`, `h`, `fit`, `fm`, `q` in that order,
78
+ after snapping. `w` and `h` appear only when given; `fit`, `fm`, and `q`
79
+ always appear once any of the five is present.
49
80
 
50
- - **A registered public recipe** (`/dam/a/{id}/email-hero.jpg`): expands
51
- server-side into a fixed parameter set from the public recipe registry.
52
- Recipe URLs are a second canonical form — no redirect hop. Adding
53
- transform query params alongside a recipe is a 400 (ambiguity is author
54
- error); ESP decorations are stripped first, as everywhere. The
55
- extension is readability only — the recipe's format wins. The registry
56
- ships empty; `GET …/permalinks` lists what is registered.
57
- - **Anything else — a readable slug** (`/dam/a/{id}/spring-sale.jpg`):
58
- answers a 301 to the canonical no-slug URL with the same (canonicalized)
59
- query. Use the slug form when a tool insists on an extension-bearing
60
- image URL; it costs one cached redirect and is stable forever.
61
-
62
- ## Response Semantics
81
+ | You write | Canonical link |
82
+ | --- | --- |
83
+ | `/dam/{id}?w=640` | `/dam/{id}?w=640&fit=max&fm=webp&q=80` |
84
+ | `/dam/{id}?q=77&w=333&utm_source=mail` | `/dam/{id}?w=256&fit=max&fm=webp&q=75` |
85
+ | `/dam/{id}?fm=jpg` | `/dam/{id}?fit=max&fm=jpg&q=80` (a format change at the original size) |
86
+ | `/dam/{id}?w=640&q=high` | `/dam/{id}?w=640&fit=max&fm=webp&q=80` (the unreadable quality is read as left out) |
87
+ | `/dam/{id}?w=abc` | `/dam/{id}?fit=max&fm=webp&q=80` (no width, but still shaped: WebP at the original size) |
88
+ | `/dam/{id}?utm_source=mail` | `/dam/{id}` (no shaping asked for, so the original) |
89
+ | `/dam/{id}/spring-sale.jpg?w=640` | `/dam/{id}?w=640`, then as the first row |
90
+
91
+ A link that is not canonical is answered with one permanent redirect
92
+ (`301`, cacheable for an hour) to the canonical link, before any image
93
+ work is done. The image itself is cached once, under the canonical link.
94
+ A slug costs its own redirect first, with the query carried over as
95
+ written.
96
+
97
+ Sites hosted on CloudFront put the query in canonical form without a
98
+ visible redirect; a slug still redirects there.
99
+
100
+ ## Responses
101
+
102
+ Only `GET` and `HEAD` are served. Error responses are `no-store` on
103
+ Vercel and Cloudflare; on AWS CloudFront, 403 and 5xx responses may be
104
+ cached by the distribution for up to about ten seconds regardless of
105
+ `no-store`. Exact error codes differ slightly between hosting providers;
106
+ treat any 4xx as "not served".
63
107
 
64
108
  | Response | Meaning |
65
109
  | --- | --- |
66
- | 302 → `/dam/i/…` | serving: a short-lived signed inner URL (≤ 2h), re-minted per redirect |
67
- | 301 | slug normalization to the canonical URL |
68
- | 400 `no-store` | invalid value of a contract param, transform params on an SVG or alongside a recipe, malformed assetId |
69
- | 404 `no-store` | asset is not publicly served: flag off, not yet approved, embargoed, expired, archived, legal hold |
70
- | 503 `no-store` | resolution state unreadable — fail-closed, never a guess |
71
-
72
- The 302 carries a short cache TTL (default 30s) — the revocation dial.
73
- On unpublish/archive/embargo/revoking-expiry, fresh resolution dies
74
- within ≤ 30s; a flip **to** serving may additionally ride a ~10s
75
- error-caching echo. Approving a new version re-points the permalink
76
- within the same budget; already-fetched inner URLs keep serving the bytes
77
- they named until they expire (≤ 2h).
78
-
79
- ## SVG
80
-
81
- SVG permalinks are passthrough-only: the bare permalink 302s to the SVG
82
- passthrough; any transform parameter (or recipe) is a 400.
83
-
84
- ## Sanity-Style Examples
110
+ | 200, `Cache-Control: public, max-age=300` | serving |
111
+ | 301 | a slug was dropped, or the query was put in canonical form |
112
+ | 403, `no-store` | the asset has no public version (never approved, approval vetoed, demoted, archived, or expired), or the ID is malformed |
113
+ | 404, `no-store` | a retired `/dam/a/…` or `/dam/i/…` path, or DAM delivery is not enabled for the site |
114
+ | 413, `no-store` | the original is too large to shape (limits below) |
115
+ | 415, `no-store` | shaping was asked of an original that is not JPEG, PNG, WebP, or AVIF |
116
+ | 503, `no-store` | delivery could not read its own state; it refuses rather than guess |
117
+
118
+ The five-minute `max-age` is the whole revocation story. After a
119
+ take-down, an already-cached copy can keep showing for up to five minutes;
120
+ the next uncached request is checked again and refused. A newly approved
121
+ version takes over the link within the same window. This holds for Vercel
122
+ and Cloudflare; on AWS CloudFront, cached copies can currently outlive the
123
+ window — the image pipeline sets a one-year TTL and the distribution
124
+ permits it — until the hosting lane is corrected.
125
+
126
+ ## Originals That Are Not Shaped
127
+
128
+ - **No query:** the approved file is streamed byte for byte, whatever its
129
+ size.
130
+ - **Shapeable originals** are JPEG, PNG, WebP, and AVIF.
131
+ - **Everything else** (SVG, GIF, PDF, video, documents) is served only as
132
+ a file download (`Content-Disposition: attachment`, with
133
+ `X-Content-Type-Options: nosniff`) and never displayed inline. An
134
+ `<img>` pointing at such a link will not render. On AWS CloudFront this
135
+ holds only once the hosting fix (PR #709) has rolled out to the tenant;
136
+ until then that lane may serve SVG or HTML inline.
137
+ - **Size limits for shaping:** the original must be at most 20 MB, at most
138
+ 8192 pixels on either side, and at most 40 megapixels. Past any of
139
+ those, a shaped link is refused; the plain link still serves the
140
+ original. Provider gap: the AWS CloudFront lane does not currently
141
+ enforce these bounds, so an over-limit request is not refused there — do
142
+ not rely on enforcement on CloudFront.
143
+
144
+ ## Examples
85
145
 
86
146
  ```html
87
147
  <!-- Fixed-size email hero, JPEG for Outlook, explicit quality.
88
148
  640 and 384 are ladder rungs; keep the HTML width/height on the same
89
149
  rungs so the served crop and the layout box agree exactly -->
90
- <img src="https://www.example.com/dam/a/ast_2E9qL0001aBcDeF?w=640&h=384&fit=crop&fm=jpg&q=80"
150
+ <img src="https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=640&h=384&fit=crop&fm=jpg&q=80"
91
151
  width="640" height="384" alt="Spring sale hero">
92
152
 
93
- <!-- Responsive srcset on ladder rungs (no dpr param — use w) -->
94
- <img src="https://www.example.com/dam/a/ast_2E9qL0001aBcDeF?w=828"
95
- srcset="https://www.example.com/dam/a/ast_2E9qL0001aBcDeF?w=640 640w,
96
- https://www.example.com/dam/a/ast_2E9qL0001aBcDeF?w=828 828w,
97
- https://www.example.com/dam/a/ast_2E9qL0001aBcDeF?w=1200 1200w"
153
+ <!-- Responsive srcset on ladder rungs, canonical form (no dpr — use w) -->
154
+ <img src="https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=828&fit=max&fm=webp&q=80"
155
+ srcset="https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=640&fit=max&fm=webp&q=80 640w,
156
+ https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=828&fit=max&fm=webp&q=80 828w,
157
+ https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=1200&fit=max&fm=webp&q=80 1200w"
98
158
  sizes="(max-width: 640px) 100vw, 640px" alt="…">
99
159
 
100
- <!-- Extension-bearing slug form for ESP editors that validate by extension:
101
- one cached 301 to the canonical URL, stable forever -->
102
- https://www.example.com/dam/a/ast_2E9qL0001aBcDeF/spring-sale.jpg?w=640&fm=jpg
160
+ <!-- Slug form for editors that check for a file extension: one cached
161
+ redirect to the link without the slug. The extension is cosmetic;
162
+ fm still picks the format -->
163
+ https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR/spring-sale.jpg?w=640&fit=max&fm=jpg&q=80
103
164
  ```
104
165
 
105
- Quantization in practice: `?w=333&q=77` and `?w=256&q=75` serve the
106
- identical rendition (333 snaps to 256, 77 snaps to 75) — do not expect
107
- pixel-exact widths off the ladder.
108
-
109
- ## The Flag, the Gate, and the Warning
110
-
111
- - `lifecycle.publicDelivery` (asset-level, governance PATCH) is the one
112
- admission act. Flip-on passes the eligibility gate against the version
113
- the permalink would serve; refusal is a typed 400
114
- `dam.delivery.public_flip_denied` with `details.reason` (e.g.
115
- `no_approved_version`, `not_image`, `source_too_large`, a
116
- `block_new_usage` restriction, a publication-less license, an
117
- unenforceable expiry action).
118
- - Version selection is automatic and fail-closed: the latest approved,
119
- deliverable version whose license (when present) grants `publication`
120
- and whose `expiresAt` (when set) the lane can actually enforce
121
- (`unpublish`/`block_all_usage`). Versions failing those rows are
122
- skipped in favor of the previous passing one.
123
- - `GET …/permalinks` returns `warning: "block_new_usage_in_force"` when
124
- `block_new_usage` governance landed on an already-public asset (the
125
- flip gate refuses it up front, so this only happens for governance
126
- added after the flip). The permalink keeps serving — the lane cannot
127
- distinguish existing placements from new ones — so treat the warning as
128
- a prompt to review the asset's public status.
129
- - Legal hold: flipping a legal-held asset on succeeds but the permalink
130
- 404s for the hold's duration and starts serving the moment the hold
131
- lifts — no re-flip needed.
166
+ Snapping in practice: `?w=333&q=77` and `?w=256&q=75` serve the identical
167
+ rendition (333 snaps to 256, 77 snaps to 75).
@@ -0,0 +1,74 @@
1
+ # Seed DAM assets
2
+
3
+ This folder is a local, file-based copy of two DAM assets. The sample pages
4
+ reference them so the starter renders images without a running DAM service.
5
+ Copy one of the seed folders to mock a new asset for a page.
6
+
7
+ ## How a page references an asset
8
+
9
+ A component prop holds a `dam.assetRef` object. The home page hero uses it:
10
+
11
+ ```json
12
+ "image": {
13
+ "$type": "dam.assetRef",
14
+ "assetId": "000000000000000000000000101",
15
+ "alt": "Light abstract hero background with satellite constellation"
16
+ }
17
+ ```
18
+
19
+ - `assetId` — must match the `assetId` in one `asset.json` under `folders/`
20
+ - `alt` — optional; omit it to use the `altText` from `editorial.json`
21
+ - `version` — optional; omit it to use the newest approved version
22
+
23
+ The component schema (see `patterns/components/home_hero.json`) declares the
24
+ prop as `gradial.image`, not `dam.assetRef`. That is expected. The content
25
+ build resolves the ref and writes the `gradial.image` shape, with `sources`
26
+ filled in, into the compiled page. You author the ref; the build materializes
27
+ the image.
28
+
29
+ ## What one seed asset contains
30
+
31
+ Each asset is one folder under `folders/<group>/<assetId>/` plus one
32
+ content-addressed blob under `blobs/`. The local build scans every
33
+ `asset.json` under `folders/`, so the group name (`seed`) does not matter
34
+ for rendering. `aci content push` does use it: the path under `folders/`
35
+ becomes the folder path in the remote DAM.
36
+
37
+ ```
38
+ folders/seed/<assetId>/asset.json dam.asset: id and audit fields
39
+ folders/seed/<assetId>/editorial.json dam.editorial: title, altText, tags
40
+ folders/seed/<assetId>/governance.json dam.governance: asset status and per-version approval
41
+ folders/seed/<assetId>/versions/v0001.json dam.assetVersion: blob key, sha256, mime, dimensions
42
+ blobs/sha256/<aa>/<bb>/<sha256> the raw image bytes
43
+ ```
44
+
45
+ ## Add a new mocked asset
46
+
47
+ This is a step-by-step procedure.
48
+
49
+ 1. Pick an asset ID. Use 27 base62 characters. The seed IDs pad a small
50
+ number with leading zeros, for example `000000000000000000000000103`.
51
+ 2. Compute the SHA-256 of the image file. Copy the file to
52
+ `blobs/sha256/<first 2 hex>/<next 2 hex>/<full sha256>` with no extension.
53
+ 3. Copy `folders/seed/000000000000000000000000101/` to a new folder named
54
+ after the new asset ID.
55
+ 4. In `asset.json`, set `assetId` to the new ID.
56
+ 5. In `versions/v0001.json`, set `blob.sha256`, `blob.key`, `blob.byteSize`,
57
+ `blob.mime`, `blob.originalFilename`, and `technical.dimensions`.
58
+ 6. In `editorial.json`, set `altText`. The build fails on an empty alt text
59
+ when the page ref does not supply its own `alt`.
60
+ 7. In `governance.json`, keep `asset.status` as `active` and the version
61
+ `status` as `approved`. The build applies the same eligibility gate as
62
+ production and rejects a draft, embargoed, or restricted version.
63
+ 8. Reference the new ID from a page prop with `"$type": "dam.assetRef"`.
64
+
65
+ ## Serving bytes locally
66
+
67
+ The content build only needs the metadata files to compile a page. To serve
68
+ the image bytes from the local object store, run from the repo root:
69
+
70
+ ```sh
71
+ scripts/seed-local-dam-minio.sh packages/sdk/templates/common/starter-content/.content
72
+ ```
73
+
74
+ The script uploads every blob referenced by a `versions/*.json` file.
@@ -17,7 +17,8 @@
17
17
  "license": {
18
18
  "kind": "unsplash-local-fixture"
19
19
  },
20
- "publicationRestriction": "none"
20
+ "publicationRestriction": "none",
21
+ "deliveryTier": "public"
21
22
  }
22
23
  }
23
24
  }
@@ -17,7 +17,8 @@
17
17
  "license": {
18
18
  "kind": "unsplash-local-fixture"
19
19
  },
20
- "publicationRestriction": "none"
20
+ "publicationRestriction": "none",
21
+ "deliveryTier": "public"
21
22
  }
22
23
  }
23
24
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "button",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "container",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "feature_card",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "feature_grid",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "home_hero",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -54,9 +54,13 @@
54
54
  "type": "string",
55
55
  "minLength": 1
56
56
  },
57
- "srcset": {
58
- "type": "string",
59
- "minLength": 1
57
+ "widths": {
58
+ "type": "array",
59
+ "items": {
60
+ "type": "integer",
61
+ "exclusiveMinimum": 0,
62
+ "maximum": 9007199254740991
63
+ }
60
64
  },
61
65
  "width": {
62
66
  "type": "integer",
@@ -68,6 +72,13 @@
68
72
  "minimum": 0,
69
73
  "maximum": 9007199254740991
70
74
  },
75
+ "fit": {
76
+ "type": "string",
77
+ "enum": [
78
+ "max",
79
+ "crop"
80
+ ]
81
+ },
71
82
  "sizes": {
72
83
  "type": "string",
73
84
  "minLength": 1
@@ -82,7 +93,6 @@
82
93
  }
83
94
  },
84
95
  "required": [
85
- "src",
86
96
  "type"
87
97
  ],
88
98
  "additionalProperties": false
@@ -92,7 +102,6 @@
92
102
  "required": [
93
103
  "$type",
94
104
  "assetId",
95
- "versionId",
96
105
  "alt",
97
106
  "sources"
98
107
  ],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "personalization_choice",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "site-footer",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "site-navigation",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
- "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
3
+ "buildId": "codebuild_01a12331-b86d-7d20-8a35-a7a71d96e8be",
4
+ "codeDigest": "sha256:f1246860864e55359c7ad442a7a956b61a835a4826cd6229cc9971db1fe29a67",
5
5
  "name": "stats_bar",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.