@aglyn/plugins-marketplace 1.3.0 → 1.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/plugins-marketplace",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,19 +25,19 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.3.0",
29
- "@aglyn/aglyn-markdown-editor": "1.3.0",
30
- "@aglyn/shared-data-enums": "1.3.0",
31
- "@aglyn/shared-data-mdi": "1.3.0",
32
- "@aglyn/shared-ui-jsx": "1.3.0",
33
- "@aglyn/shared-ui-next": "1.3.0",
34
- "@aglyn/shared-ui-snackstack": "1.3.0",
35
- "@aglyn/shared-util-email": "1.3.0",
36
- "@aglyn/shared-util-http": "1.3.0",
37
- "@aglyn/shared-util-timestamp": "1.3.0",
38
- "@aglyn/tenant-data-admin": "1.3.0",
39
- "@aglyn/tenant-feature-instance": "1.3.0",
40
- "@aglyn/tenant-runtime": "1.3.0",
28
+ "@aglyn/aglyn": "1.5.0",
29
+ "@aglyn/aglyn-markdown-editor": "1.5.0",
30
+ "@aglyn/shared-data-enums": "1.5.0",
31
+ "@aglyn/shared-data-mdi": "1.5.0",
32
+ "@aglyn/shared-ui-jsx": "1.5.0",
33
+ "@aglyn/shared-ui-next": "1.5.0",
34
+ "@aglyn/shared-ui-snackstack": "1.5.0",
35
+ "@aglyn/shared-util-email": "1.5.0",
36
+ "@aglyn/shared-util-http": "1.5.0",
37
+ "@aglyn/shared-util-timestamp": "1.5.0",
38
+ "@aglyn/tenant-data-admin": "1.5.0",
39
+ "@aglyn/tenant-feature-instance": "1.5.0",
40
+ "@aglyn/tenant-runtime": "1.5.0",
41
41
  "@swc/helpers": "0.5.23"
42
42
  },
43
43
  "peerDependencies": {
@@ -106,8 +106,20 @@
106
106
  * merchant of record and determines, collects and remits transaction tax since
107
107
  * 2026-08-14. The Terms of Service moved TO them in this pass (new ToS §10.7),
108
108
  * not the other way around.
109
+ *
110
+ * ## 2026-11-02 — `2026-11-02.1`, site starters (AGL-4049)
111
+ *
112
+ * The opening names site starters among the Artifacts, and §1 is now "Site
113
+ * Starters": a site starter is an Artifact and everything in it is warranted
114
+ * under §3. That replaces §1's pre-release paragraph. Its "AS IS" wording stays
115
+ * in §10, and the right to change the Marketplace stays in Terms of Service
116
+ * §5.1. §2 to §14 keep their numbers, because the repo and the native screens
117
+ * cite them.
118
+ *
119
+ * The capture also carries §8.6's "license" spelling, which the page already
120
+ * served after the `2026-08-24.1` pin was taken.
109
121
  */
110
- export declare const PUBLISHER_AGREEMENT_VERSION = "2026-08-24.1";
122
+ export declare const PUBLISHER_AGREEMENT_VERSION = "2026-11-02.1";
111
123
  export declare const PUBLISHER_AGREEMENT_TITLE = "Marketplace Publisher Agreement";
112
124
  /**
113
125
  * The snapshot pin for the version above (AGL-1678).
@@ -144,9 +156,9 @@ export declare const PUBLISHER_AGREEMENT_TITLE = "Marketplace Publisher Agreemen
144
156
  * hand-write a snapshot: it is evidence of what a publisher was shown, and a
145
157
  * snapshot of unpublished text is a false record.
146
158
  */
147
- export declare const PUBLISHER_AGREEMENT_SHA256 = "2df6e940f037b4630e53c8f63bad8604ef4bf370374b89afcd4ea7f9fe8e8d63";
159
+ export declare const PUBLISHER_AGREEMENT_SHA256 = "3a345609a30e915be53dfeaf8e4a2c141e92a250e39cf741f8c8c0c9c764d23c";
148
160
  /** Byte length of the same snapshot — a cheap second check on the content. */
149
- export declare const PUBLISHER_AGREEMENT_BYTES = 13730;
161
+ export declare const PUBLISHER_AGREEMENT_BYTES = 13709;
150
162
  /**
151
163
  * Canonical document, on the operator's legal origin beside the other terms.
152
164
  *
@@ -129,7 +129,19 @@
129
129
  * merchant of record and determines, collects and remits transaction tax since
130
130
  * 2026-08-14. The Terms of Service moved TO them in this pass (new ToS §10.7),
131
131
  * not the other way around.
132
- */ export const PUBLISHER_AGREEMENT_VERSION = '2026-08-24.1';
132
+ *
133
+ * ## 2026-11-02 — `2026-11-02.1`, site starters (AGL-4049)
134
+ *
135
+ * The opening names site starters among the Artifacts, and §1 is now "Site
136
+ * Starters": a site starter is an Artifact and everything in it is warranted
137
+ * under §3. That replaces §1's pre-release paragraph. Its "AS IS" wording stays
138
+ * in §10, and the right to change the Marketplace stays in Terms of Service
139
+ * §5.1. §2 to §14 keep their numbers, because the repo and the native screens
140
+ * cite them.
141
+ *
142
+ * The capture also carries §8.6's "license" spelling, which the page already
143
+ * served after the `2026-08-24.1` pin was taken.
144
+ */ export const PUBLISHER_AGREEMENT_VERSION = '2026-11-02.1';
133
145
  export const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement';
134
146
  /**
135
147
  * The snapshot pin for the version above (AGL-1678).
@@ -165,8 +177,8 @@ export const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement';
165
177
  * the version's entry to `PUBLISHER_AGREEMENT_CHANGES` below. Never
166
178
  * hand-write a snapshot: it is evidence of what a publisher was shown, and a
167
179
  * snapshot of unpublished text is a false record.
168
- */ export const PUBLISHER_AGREEMENT_SHA256 = '2df6e940f037b4630e53c8f63bad8604ef4bf370374b89afcd4ea7f9fe8e8d63';
169
- /** Byte length of the same snapshot — a cheap second check on the content. */ export const PUBLISHER_AGREEMENT_BYTES = 13730;
180
+ */ export const PUBLISHER_AGREEMENT_SHA256 = '3a345609a30e915be53dfeaf8e4a2c141e92a250e39cf741f8c8c0c9c764d23c';
181
+ /** Byte length of the same snapshot — a cheap second check on the content. */ export const PUBLISHER_AGREEMENT_BYTES = 13709;
170
182
  /**
171
183
  * Canonical document, on the operator's legal origin beside the other terms.
172
184
  *
@@ -277,6 +289,14 @@ export const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement';
277
289
  changes: [
278
290
  '§13.3: venue moves to Travis County, Texas, and governing law now cites Terms of Service Section 18.6.'
279
291
  ]
292
+ },
293
+ {
294
+ version: '2026-11-02.1',
295
+ changes: [
296
+ 'Opening paragraph: site starters are among the Artifacts you can publish.',
297
+ '§1, new: a site starter is an Artifact. Its pages, shared layout, theme and, for an AI site starter, its answers are its content, and you warrant them under §3. §1 no longer describes the Marketplace as pre-release.',
298
+ '§8.6: a spelling correction, with no change in meaning.'
299
+ ]
280
300
  }
281
301
  ];
282
302
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/model/publisher-agreement.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The marketplace publisher agreement, and the box a publisher ticks to agree\n * to it on every save (AGL-1077, AGL-4105).\n *\n * Deliberately NOT the per-version attestation (AGL-969). An attestation is\n * a statement about *specific bytes*. This is about the *relationship*: what\n * we may do with a listing, what the publisher warrants, indemnity, takedown,\n * payouts, what survives termination.\n *\n * It was accepted once per organization and version, in a dialog. Since\n * AGL-4105 it is agreed to on EVERY publisher save instead: a profile, a\n * listing's words and pictures, its price or visibility, a version, a\n * component, template or layout. Each save form carries an unticked\n * \"I agree to the Marketplace Publisher Agreement\" box above its button, the\n * request carries {@link PublisherAgreementConsent}, and the route refuses a\n * write without it and records the acceptance. The org's `publisherAgreement`\n * stays as a note of the last acceptance (staff read it on the review page);\n * it no longer gates anything.\n *\n * Shared like the attestation model is, and for the same reason: every\n * publisher route enforces it, the console and the apps send it, and the\n * review page shows staff which terms a publisher is under. Copies of a\n * version string would drift.\n */\n\nimport { LEGAL_ORIGIN, isPublishedLegalUrl } from '@aglyn/aglyn/app-utils/published-legal-pages'\n\n/**\n * The version of the agreement currently in force.\n *\n * Matches the `Agreement version` header of the document itself, which is now\n * besigner content at {@link PUBLISHER_AGREEMENT_URL} rather than a repo file\n * (same practice as the Terms of Service). Bump this **only** when the\n * substance changes in a way a publisher should re-read — a typo fix is not a\n * bump. Bumping it stops every publisher at their next publish until they\n * accept again.\n *\n * Moved off `2026-07-28.1` on 2026-08-14 (AGL-1674). That string named the\n * July draft, which was never published and whose §8 said the publisher is the\n * seller of record. The published text says the opposite — Aglyn processes the\n * sale and remits transaction tax — so it is a different document in\n * substance, not a reissue, and re-asking is the point rather than a cost.\n *\n * Moved to `2026-08-18.1` on 2026-08-18 (AGL-1840 + AGL-1661). Two body-text\n * changes: §1 now says \"the Aglyn marketplace\" (the AGL-975 rename, and the\n * reason this snapshot must NOT need the AGL-975 naming-guard exemption that\n * the `2026-08-14.1` one still carries), and §1's cross-reference to\n * the \"End User Licence Agreement\"\n * becomes \"License\" to match the document that agreement actually is, which\n * was renamed on the same day.\n *\n * ⚠️ Read against the \"a typo fix is not a bump\" rule above, both edits are\n * closer to a typo than to substance, and the tension is real. The bump was\n * taken anyway on the decision (2026-08-18), for a reason the rule does not\n * cover: the served page changed, so keeping `2026-08-14.1` would leave the\n * pin below asserting a hash for text nobody is shown any more — a FALSE\n * RECORD, which is the exact failure the pin exists to detect. The choice is\n * therefore between a bump and a broken pin, not between a bump and nothing.\n *\n * ## 2026-08-22 — the page changed and this string DELIBERATELY did not\n *\n * Three clauses were added on 2026-08-22 (§3(h) listing conduct, §8.6 sales\n * through the Marketplace, §13.6 marks) and the pin below moved with them, but\n * `2026-08-18.1` stayed. That is not the third option the paragraph above says\n * does not exist — it is the same choice with one input changed. A bump exists\n * to re-ask publishers who accepted the OLD text; production holds exactly one\n * acceptance record and it is the own, so there is nobody to re-ask and the\n * bump would buy nothing. the decision, 2026-08-22.\n *\n * The pin still had to move, for precisely the reason given above: the served\n * bytes changed, so leaving the old hash here would assert a document nobody\n * is shown. Version unchanged + pin re-captured is coherent ONLY while the\n * acceptance set is empty. The first real publisher acceptance ends that, and\n * from then on any body-text change costs a bump — see the same rule in\n * `apps/console/constants/legal-documents.ts`, where the clickwrap snapshots\n * collapsed back to `v1` on the identical argument.\n *\n * ## 2026-08-24 — `2026-08-24.1`, and why this one CANNOT be folded (AGL-1956)\n *\n * §13.3 changed twice in one sentence. The venue moved from Williamson County\n * to TRAVIS County (decided) — Williamson entered from the former\n * Jarrell residential address, while every published Aglyn address is 5900\n * Balcones Dr STE 100, Austin, TX 78731, which is Travis. And the clause cited\n * \"Terms of Service Section 19\" for governing law and venue when those live at\n * §18.6; §19 is General. A wrong cross-reference in a forum-selection clause is\n * the kind of defect that gets argued about, so it was corrected in the same\n * pass.\n *\n * Unlike 2026-08-22, this one takes the bump rather than only re-pinning, and\n * the deciding reason is mechanical rather than editorial: THIS VERSION STRING\n * IS PUBLISHED IN THE DOCUMENT. The page at {@link PUBLISHER_AGREEMENT_URL}\n * serves `Agreement version: 2026-08-24.1` in its own second line, so the\n * capture below contains it, and `publisher-agreement-version.spec.ts` asserts\n * the snapshot contains `Agreement version: ${PUBLISHER_AGREEMENT_VERSION}`.\n * Holding the constant at `2026-08-18.1` against that text would need the page\n * republished to say so, and would otherwise record a publisher as having\n * accepted `2026-08-18.1` while naming bytes that call themselves\n * `2026-08-24.1`. That is a false record of exactly the shape the pin exists\n * to prevent.\n *\n * ⚠️ THIS IS THE ONE PLACE THE CLICKWRAP ARGUMENT DOES NOT REACH. The signup\n * clickwrap folded its 2026-08-24 corrections into `v1` and did not bump\n * (`apps/console/constants/legal-documents.ts`) — decided: no v2\n * before launch. That works there because `v1` is a REPO-SIDE label: the\n * published Terms carry a \"Last updated\" date and no version string at all, so\n * the label can stay still while the text moves. Here the label is part of the\n * document a publisher reads. The two schemes are not the same kind of thing\n * and must not be reasoned about as one — that difference is the whole content\n * of this paragraph.\n *\n * On the merits it would have been a bump anyway: a forum-selection clause is\n * substance, not a typo — it names the court a publisher would have to travel\n * to. The 2026-08-22 cost argument is unchanged and still cheap, production\n * holding exactly one acceptance record which is the own.\n *\n * §8.1 and §8.3 are UNTOUCHED and were already correct: they have said Aglyn is\n * merchant of record and determines, collects and remits transaction tax since\n * 2026-08-14. The Terms of Service moved TO them in this pass (new ToS §10.7),\n * not the other way around.\n */\nexport const PUBLISHER_AGREEMENT_VERSION = '2026-08-24.1'\n\nexport const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement'\n\n/**\n * The snapshot pin for the version above (AGL-1678).\n *\n * A version string is a label we control and can reuse, so on its own it\n * proves nothing about what a publisher actually read. These two values pin\n * the archived snapshot at\n * `legal/publisher-agreement/{PUBLISHER_AGREEMENT_VERSION}/marketplace-publisher-agreement.txt`\n * (beside this module), captured FROM THE LIVE PAGE after publication — the\n * same publication-first machinery as the signup clickwrap\n * (`apps/console/constants/legal-documents.ts`, AGL-1497), and deliberately a\n * PARALLEL manifest rather than an entry in `LEGAL_DOCUMENTS`: ToS §19.1 makes\n * that set the entire signup agreement, and the publisher agreement is\n * deliberately not part of it. Mixing them would widen what a signup\n * acceptance covers.\n *\n * Both values go onto every acceptance record, so a record is self-contained\n * evidence of content and later tampering with the archive is detectable\n * rather than invisible. `publisher-agreement-version.spec.ts` re-hashes the\n * snapshot, so one version string can never come to mean two different\n * documents.\n *\n * Capture method (proven byte-for-byte against the clickwrap v4 hashes before\n * this snapshot was taken): fetch the live page, walk its HTML text nodes\n * skipping script/style, trim each, drop empties, take the document's content\n * block (first line `Last updated: …` through its closing `© …` line,\n * excluding site chrome and the table of contents), join with `\\n`, and end\n * with a trailing newline. UTF-8 throughout.\n *\n * TO PUBLISH A CHANGE: publish the besigner edit first, confirm the live page\n * serves it, capture a new snapshot under the new version's directory, then\n * bump `PUBLISHER_AGREEMENT_VERSION` and these two values together, and add\n * the version's entry to `PUBLISHER_AGREEMENT_CHANGES` below. Never\n * hand-write a snapshot: it is evidence of what a publisher was shown, and a\n * snapshot of unpublished text is a false record.\n */\nexport const PUBLISHER_AGREEMENT_SHA256 =\n '2df6e940f037b4630e53c8f63bad8604ef4bf370374b89afcd4ea7f9fe8e8d63'\n\n/** Byte length of the same snapshot — a cheap second check on the content. */\nexport const PUBLISHER_AGREEMENT_BYTES = 13730\n\n/**\n * Canonical document, on the operator's legal origin beside the other terms.\n *\n * Built from `LEGAL_ORIGIN` (AGL-2196), which this module already depends on:\n * `publisherAgreementIsPublished` below calls `isPublishedLegalUrl`, and that\n * accepts ONLY `LEGAL_ORIGIN`. So the gate was operator-aware while the link\n * it gates was a bare `aglyn.com` literal — meaning on a self-host install\n * with `NEXT_PUBLIC_OPERATOR_LEGAL_ORIGIN` set, the gate rejected the very URL\n * this file handed it, and every publisher was blocked from accepting. One\n * origin for both closes that, and leaves Aglyn's own URL byte-identical.\n */\nexport const PUBLISHER_AGREEMENT_URL = `${LEGAL_ORIGIN}/legal/marketplace-publisher-agreement`\n\n/**\n * Whether that document can actually be read (AGL-1660).\n *\n * It could not, from the day this gate shipped until the day this check did:\n * the URL above 404ed, and the console still rendered it as \"Read the full\n * Marketplace Publisher Agreement\" above an Accept button. An acceptance\n * collected that way is a signature on a blank page — the same\n * publication-first principle the clickwrap snapshots are built on, failing in\n * the one place the text was never published at all.\n *\n * Derived, not a second flag: it reads `PUBLISHED_LEGAL_PATHS`, so the ONE\n * edit that adds the path when the page goes live is what re-opens acceptance\n * everywhere. There is no boolean to forget to flip, and no way for the link\n * and the gate to disagree.\n */\nexport function publisherAgreementIsPublished(\n url: string = PUBLISHER_AGREEMENT_URL,\n): boolean {\n return isPublishedLegalUrl(url)\n}\n\n/**\n * What a publisher is told while the document has no page.\n *\n * Deliberately not \"try again later\" — it names the reason, because the fix is\n * ours and the publisher can do nothing about it. It must never read as though\n * accepting is something they merely have not got round to.\n */\nexport const PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE =\n `The ${PUBLISHER_AGREEMENT_TITLE} is not published yet, so there is ` +\n 'nothing here for you to read — and we will not ask you to agree to a ' +\n 'document we have not shown you. Acceptance is paused until it is ' +\n 'available, which also means marketplace publishing is paused. Nothing is ' +\n 'required of you in the meantime.'\n\n/**\n * What the agreement actually commits a publisher to.\n *\n * Shown above the accept control. A link alone is the pattern that produces\n * agreements nobody has read; these are the terms most likely to surprise\n * someone later, in the words they would need at that moment. They summarise\n * the document — they are not it, and the copy says so.\n */\nexport const PUBLISHER_AGREEMENT_POINTS: readonly {\n id: string\n label: string\n detail: string\n}[] = [\n {\n id: 'hosting-license',\n label: 'We may host, verify and distribute what you publish',\n detail:\n 'Including keeping an immutable copy of every version, inspecting its code, and showing your listing content in the marketplace and console.',\n },\n {\n id: 'warranties',\n label: 'You warrant each version as you publish it',\n detail:\n 'That you have the right to publish it, that its license is accurate and compatible, that it carries no malware or hidden telemetry, and that its documentation describes what it does with data.',\n },\n {\n id: 'immutable',\n label: 'You cannot recall code that is already installed',\n detail:\n 'Installs pin an exact version and hash. A mistake ships until an installer chooses to upgrade — publishing a new version is the only remedy you have.',\n },\n {\n id: 'revocation',\n label: 'We can disable a version everywhere, without notice',\n detail:\n 'If a version looks like a security, legal or privacy risk we stop it on every site running it, and tell you afterwards. Operating a platform that executes other people’s code requires this.',\n },\n {\n id: 'review',\n label: 'Review is a safety screen, not an endorsement',\n detail:\n 'Approval is not an audit and not a guarantee your plugin works. We may decline, delist or unsign anything, for reasons that may have nothing to do with your code.',\n },\n {\n id: 'payouts',\n label: 'On paid listings we process the sale and take a fee',\n detail:\n 'We process the purchase and pay your share into your own Stripe Connect account, less a platform fee that may change. We collect and remit sales tax on Marketplace sales; refunds, chargebacks and support on your Artifacts are yours.',\n },\n {\n id: 'indemnity',\n label: 'You indemnify us for claims arising from what you publish',\n detail:\n 'Including infringement claims and disputes with the organizations that install it.',\n },\n]\n\n/**\n * What each version changed from the one before it, in the words a publisher\n * re-accepting needs (AGL-3407).\n *\n * An org that accepted an older version is asked again, and \"the terms\n * changed\" with nothing more is a request to re-read thirteen sections to\n * find two edited clauses. Each entry names the sections that moved, read off\n * the archived snapshots beside this module (`legal/publisher-agreement/`) —\n * never written from memory of the edit, for the same reason a snapshot is\n * never hand-written.\n *\n * Oldest first. The last entry is always {@link PUBLISHER_AGREEMENT_VERSION}:\n * a bump adds its entry in the same change, and\n * `publisher-agreement-version.spec.ts` fails a bump that did not. The first\n * published version has no entry, because nothing preceded it that anyone\n * accepted.\n */\nexport const PUBLISHER_AGREEMENT_CHANGES: readonly {\n version: string\n changes: readonly string[]\n}[] = [\n {\n version: '2026-08-18.1',\n changes: [\n '§1 names the marketplace and the End User License Agreement by their current names.',\n '§3(h), new: listing conduct — what an Artifact and its listing may not claim about the platform, its plans or its prices.',\n '§8.6, new: a paid Artifact, tier or license key must be sold through the Marketplace.',\n '§13.6, new: how you may use the platform’s names and marks.',\n ],\n },\n {\n version: '2026-08-24.1',\n changes: [\n '§13.3: venue moves to Travis County, Texas, and governing law now cites Terms of Service Section 18.6.',\n ],\n },\n]\n\n/**\n * The changes an org has not yet accepted, oldest first.\n *\n * Versions are dated strings (`YYYY-MM-DD.n`), so they order as text. An\n * acceptance of a version this list does not name — one older than the first\n * entry — gets every entry, which is the honest answer: all of it is new to\n * them. No acceptance at all gets none, because a first acceptance is of the\n * whole document, not a set of edits.\n */\nexport function publisherAgreementChangesSince(\n acceptedVersion: string | null | undefined,\n currentVersion: string = PUBLISHER_AGREEMENT_VERSION,\n): readonly { version: string; changes: readonly string[] }[] {\n const accepted = typeof acceptedVersion === 'string' ? acceptedVersion.trim() : ''\n if (!accepted) return []\n return PUBLISHER_AGREEMENT_CHANGES.filter(\n (entry) => entry.version > accepted && entry.version <= currentVersion,\n )\n}\n\n/**\n * The org's last acceptance, as `publisherProfiles/{orgId}.publisherAgreement`\n * notes it: which version, of which exact bytes, by whom, when. Rewritten by\n * every save since AGL-4105, beside the append-only record of each one\n * ({@link PublisherAgreementAcceptanceRecord}).\n *\n * `sha256`/`bytes` (AGL-1678) pin the acceptance to the archived snapshot of\n * the text the publisher was shown. Optional because records written before\n * the pin existed carry only the version string — absence means \"accepted\n * before 2026-08-17\", not \"accepted nothing\".\n */\nexport interface PublisherAgreementAcceptance {\n version?: string\n sha256?: string\n bytes?: number\n acceptedBy?: string\n acceptedAt?: unknown\n}\n\n/**\n * Where an org stands with the agreement.\n *\n * `none` and `outdated` are deliberately different answers. \"You have never\n * agreed to anything\" and \"the terms changed since you agreed\" are different\n * situations with different copy, and collapsing them into a boolean is how\n * a re-acceptance ends up reading like a first-time setup step.\n */\nexport type PublisherAgreementState = 'none' | 'outdated' | 'current'\n\nexport function publisherAgreementState(\n acceptance: PublisherAgreementAcceptance | null | undefined,\n currentVersion: string = PUBLISHER_AGREEMENT_VERSION,\n): PublisherAgreementState {\n const accepted = acceptance?.version\n if (typeof accepted !== 'string' || !accepted.trim()) return 'none'\n return accepted === currentVersion ? 'current' : 'outdated'\n}\n\n/**\n * Whether an org's last acceptance is of the version in force.\n *\n * A note since AGL-4105, not a gate: every save agrees again on its own\n * ({@link publisherAgreementConsentRefusal}). Read by the first-party starter\n * seeding script, which writes listings without a save form.\n */\nexport function hasCurrentPublisherAgreement(\n acceptance: PublisherAgreementAcceptance | null | undefined,\n currentVersion: string = PUBLISHER_AGREEMENT_VERSION,\n): boolean {\n return publisherAgreementState(acceptance, currentVersion) === 'current'\n}\n\n/**\n * What the acceptance UI may show (AGL-1660).\n *\n * The gate lives HERE rather than in the panel, for the reason every \"check it\n * in the component\" control eventually fails: the component is not the only\n * caller. The accept route consults the same function, so a client that skips\n * the UI entirely meets the same answer.\n *\n * `documentUrl` is null, not the URL, when the document is unpublished — the\n * console reads the link target from this, so an unreadable document is\n * structurally unable to reach an href.\n */\nexport interface PublisherAgreementPresentation {\n /** The document to link, or null when there is no page to link to. */\n documentUrl: string | null\n /** Whether the accept control may be offered at all. */\n canAccept: boolean\n /** Why acceptance is unavailable, or null when it is available. */\n unavailableNotice: string | null\n}\n\nexport function publisherAgreementPresentation(\n state: PublisherAgreementState,\n published: boolean = publisherAgreementIsPublished(),\n): PublisherAgreementPresentation {\n return {\n documentUrl: published ? PUBLISHER_AGREEMENT_URL : null,\n // Already current is not \"cannot accept because unpublished\" — it is\n // nothing left to do, and the panel says so separately.\n canAccept: published && state !== 'current',\n unavailableNotice: published ? null : PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE,\n }\n}\n\n/*==========================================\n * AGREED TO ON EVERY SAVE (AGL-4105).\n *\n * Every publisher save — a profile, a listing's words, pictures, categories,\n * price or visibility, unpublishing or republishing it, a version, a\n * component, template, theme, layout, dataset schema or email, asking for the\n * Verified badge — carries {@link PublisherAgreementConsent}. The console and\n * the apps send it only while the person has ticked the box above the button,\n * and the box is unticked again after every save, so each save is its own\n * agreement. The routes refuse a write without it\n * ({@link publisherAgreementConsentRefusal}) and record who agreed, to which\n * version, for what, and from where.\n *=========================================*/\n\n/** What a save sends while its box is ticked: the version it agrees to. */\nexport interface PublisherAgreementConsent {\n version: string\n accepted: true\n}\n\n/** The box's sentence; the agreement's title in it is the link to the document. */\nexport const PUBLISHER_AGREEMENT_CONSENT_LABEL = `I agree to the ${PUBLISHER_AGREEMENT_TITLE}`\n\n/** What a save without the box ticked is told. */\nexport const PUBLISHER_AGREEMENT_CONSENT_REQUIRED = `Tick '${PUBLISHER_AGREEMENT_CONSENT_LABEL}' to save`\n\n/** What a save that agreed to an older version is told: the page was open across a change. */\nexport const PUBLISHER_AGREEMENT_CONSENT_OUTDATED =\n `The ${PUBLISHER_AGREEMENT_TITLE} changed while this was open. Reload, read ` +\n 'the current version and tick the box again to save.'\n\n/** What a save sends once its box is ticked. */\nexport function publisherAgreementConsent(\n version: string = PUBLISHER_AGREEMENT_VERSION,\n): PublisherAgreementConsent {\n return { version, accepted: true }\n}\n\n/**\n * Why a save's `agreement` does not count, or null when it does.\n *\n * `missing`: absent, not ticked, or not this shape. `outdated`: ticked for a\n * version that is no longer in force, which is a page left open across a\n * change, not a publisher who declined. `unavailable`: the document has no\n * published page, so nothing can be agreed to (AGL-1660) whatever was sent.\n */\nexport type PublisherAgreementConsentProblem = 'missing' | 'outdated' | 'unavailable'\n\nexport function publisherAgreementConsentProblem(\n raw: unknown,\n options: { currentVersion?: string; published?: boolean } = {},\n): PublisherAgreementConsentProblem | null {\n const currentVersion = options.currentVersion ?? PUBLISHER_AGREEMENT_VERSION\n const published = options.published ?? publisherAgreementIsPublished()\n if (!published) return 'unavailable'\n const consent = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>\n if (consent['accepted'] !== true) return 'missing'\n const version = typeof consent['version'] === 'string' ? consent['version'].trim() : ''\n if (!version) return 'missing'\n return version === currentVersion ? null : 'outdated'\n}\n\n/**\n * The refusal a save without a counting `agreement` gets, or null when it may\n * go ahead. One answer for every publisher route.\n *\n * 428, like the per-version attestation (AGL-969): both say \"tick the box in\n * the form in front of you\". A version from before a change is 409, the\n * conflict-with-current-state answer the retired accept route gave the same\n * mismatch, and so is an unpublished document. `agreement` is the\n * machine-readable half, for a client that wants to point at the box.\n */\nexport function publisherAgreementConsentRefusal(\n raw: unknown,\n options: { currentVersion?: string; published?: boolean } = {},\n): { status: number; body: Record<string, unknown> } | null {\n const problem = publisherAgreementConsentProblem(raw, options)\n if (!problem) return null\n const required = options.currentVersion ?? PUBLISHER_AGREEMENT_VERSION\n const agreement = { required, state: problem }\n if (problem === 'unavailable') {\n return { status: 409, body: { error: PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE, agreement } }\n }\n if (problem === 'outdated') {\n return { status: 409, body: { error: PUBLISHER_AGREEMENT_CONSENT_OUTDATED, agreement } }\n }\n return { status: 428, body: { error: PUBLISHER_AGREEMENT_CONSENT_REQUIRED, agreement } }\n}\n\n/**\n * What the box may show (AGL-1660, AGL-4105): the link, and whether it can be\n * ticked at all. The box reads its href from here, never from\n * {@link PUBLISHER_AGREEMENT_URL}, so an unpublished document cannot reach a\n * link and cannot be agreed to.\n */\nexport interface PublisherAgreementConsentPresentation {\n /** The document to link, or null when there is no page to link to. */\n documentUrl: string | null\n /** Whether the box may be ticked. */\n canAgree: boolean\n /** Why it cannot be, or null when it can. */\n unavailableNotice: string | null\n}\n\nexport function publisherAgreementConsentPresentation(\n published: boolean = publisherAgreementIsPublished(),\n): PublisherAgreementConsentPresentation {\n return {\n documentUrl: published ? PUBLISHER_AGREEMENT_URL : null,\n canAgree: published,\n unavailableNotice: published ? null : PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE,\n }\n}\n\n/**\n * Where an acceptance came from, as its record names it: one name per\n * publisher save. Closed, so a record can always be read back as an action.\n */\nexport const PUBLISHER_AGREEMENT_ACTIONS = [\n 'save-profile',\n 'publish-component',\n 'publish-layout',\n 'publish-template',\n 'publish-starter',\n 'publish-theme',\n 'publish-dataset-schema',\n 'publish-email-template',\n 'publish-email-starter',\n 'publish-plugin',\n 'update-listing',\n 'set-preview-image',\n 'remove-preview-image',\n 'set-visibility',\n 'set-published',\n 'request-verification',\n 'withdraw-verification',\n] as const\n\nexport type PublisherAgreementAction = (typeof PUBLISHER_AGREEMENT_ACTIONS)[number]\n\n/**\n * One acceptance, as `orgs/{orgId}/publisherAgreementAcceptances/{id}` holds\n * it: append-only and server-written, with the evidence a signature's audit\n * keeps (the hardware terms' acceptance is the same shape, AGL-4038) — which\n * text, by whom, when, for which save, and from which device.\n */\nexport interface PublisherAgreementAcceptanceRecord {\n version: string\n /** The archived snapshot's pin (AGL-1678), so the record names the bytes as well as the label. */\n sha256: string\n bytes: number\n orgId: string\n uid: string\n /** Whether the person was acting as staff rather than as the publisher. */\n staff: boolean\n action: PublisherAgreementAction\n /** The listing, profile or source the save wrote, or null where it has none yet. */\n targetId: string | null\n ip: string | null\n userAgent: string | null\n atMs: number\n}\n\n/** A fresh acceptance of the agreement in force. */\nexport function publisherAgreementAcceptanceRecord(input: {\n orgId: string\n uid: string\n staff?: boolean\n action: PublisherAgreementAction\n targetId?: string | null\n ip?: string | null\n userAgent?: string | null\n atMs: number\n}): PublisherAgreementAcceptanceRecord {\n const text = (value: string | null | undefined, max: number) =>\n typeof value === 'string' && value.trim() ? value.trim().slice(0, max) : null\n return {\n version: PUBLISHER_AGREEMENT_VERSION,\n sha256: PUBLISHER_AGREEMENT_SHA256,\n bytes: PUBLISHER_AGREEMENT_BYTES,\n orgId: input.orgId,\n uid: input.uid,\n staff: input.staff === true,\n action: input.action,\n targetId: text(input.targetId, 256),\n ip: text(input.ip, 100),\n userAgent: text(input.userAgent, 400),\n atMs: input.atMs,\n }\n}\n"],"names":["LEGAL_ORIGIN","isPublishedLegalUrl","PUBLISHER_AGREEMENT_VERSION","PUBLISHER_AGREEMENT_TITLE","PUBLISHER_AGREEMENT_SHA256","PUBLISHER_AGREEMENT_BYTES","PUBLISHER_AGREEMENT_URL","publisherAgreementIsPublished","url","PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE","PUBLISHER_AGREEMENT_POINTS","id","label","detail","PUBLISHER_AGREEMENT_CHANGES","version","changes","publisherAgreementChangesSince","acceptedVersion","currentVersion","accepted","trim","filter","entry","publisherAgreementState","acceptance","hasCurrentPublisherAgreement","publisherAgreementPresentation","state","published","documentUrl","canAccept","unavailableNotice","PUBLISHER_AGREEMENT_CONSENT_LABEL","PUBLISHER_AGREEMENT_CONSENT_REQUIRED","PUBLISHER_AGREEMENT_CONSENT_OUTDATED","publisherAgreementConsent","publisherAgreementConsentProblem","raw","options","consent","publisherAgreementConsentRefusal","problem","required","agreement","status","body","error","publisherAgreementConsentPresentation","canAgree","PUBLISHER_AGREEMENT_ACTIONS","publisherAgreementAcceptanceRecord","input","text","value","max","slice","sha256","bytes","orgId","uid","staff","action","targetId","ip","userAgent","atMs"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/model/publisher-agreement.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The marketplace publisher agreement, and the box a publisher ticks to agree\n * to it on every save (AGL-1077, AGL-4105).\n *\n * Deliberately NOT the per-version attestation (AGL-969). An attestation is\n * a statement about *specific bytes*. This is about the *relationship*: what\n * we may do with a listing, what the publisher warrants, indemnity, takedown,\n * payouts, what survives termination.\n *\n * It was accepted once per organization and version, in a dialog. Since\n * AGL-4105 it is agreed to on EVERY publisher save instead: a profile, a\n * listing's words and pictures, its price or visibility, a version, a\n * component, template or layout. Each save form carries an unticked\n * \"I agree to the Marketplace Publisher Agreement\" box above its button, the\n * request carries {@link PublisherAgreementConsent}, and the route refuses a\n * write without it and records the acceptance. The org's `publisherAgreement`\n * stays as a note of the last acceptance (staff read it on the review page);\n * it no longer gates anything.\n *\n * Shared like the attestation model is, and for the same reason: every\n * publisher route enforces it, the console and the apps send it, and the\n * review page shows staff which terms a publisher is under. Copies of a\n * version string would drift.\n */\n\nimport { LEGAL_ORIGIN, isPublishedLegalUrl } from '@aglyn/aglyn/app-utils/published-legal-pages'\n\n/**\n * The version of the agreement currently in force.\n *\n * Matches the `Agreement version` header of the document itself, which is now\n * besigner content at {@link PUBLISHER_AGREEMENT_URL} rather than a repo file\n * (same practice as the Terms of Service). Bump this **only** when the\n * substance changes in a way a publisher should re-read — a typo fix is not a\n * bump. Bumping it stops every publisher at their next publish until they\n * accept again.\n *\n * Moved off `2026-07-28.1` on 2026-08-14 (AGL-1674). That string named the\n * July draft, which was never published and whose §8 said the publisher is the\n * seller of record. The published text says the opposite — Aglyn processes the\n * sale and remits transaction tax — so it is a different document in\n * substance, not a reissue, and re-asking is the point rather than a cost.\n *\n * Moved to `2026-08-18.1` on 2026-08-18 (AGL-1840 + AGL-1661). Two body-text\n * changes: §1 now says \"the Aglyn marketplace\" (the AGL-975 rename, and the\n * reason this snapshot must NOT need the AGL-975 naming-guard exemption that\n * the `2026-08-14.1` one still carries), and §1's cross-reference to\n * the \"End User Licence Agreement\"\n * becomes \"License\" to match the document that agreement actually is, which\n * was renamed on the same day.\n *\n * ⚠️ Read against the \"a typo fix is not a bump\" rule above, both edits are\n * closer to a typo than to substance, and the tension is real. The bump was\n * taken anyway on the decision (2026-08-18), for a reason the rule does not\n * cover: the served page changed, so keeping `2026-08-14.1` would leave the\n * pin below asserting a hash for text nobody is shown any more — a FALSE\n * RECORD, which is the exact failure the pin exists to detect. The choice is\n * therefore between a bump and a broken pin, not between a bump and nothing.\n *\n * ## 2026-08-22 — the page changed and this string DELIBERATELY did not\n *\n * Three clauses were added on 2026-08-22 (§3(h) listing conduct, §8.6 sales\n * through the Marketplace, §13.6 marks) and the pin below moved with them, but\n * `2026-08-18.1` stayed. That is not the third option the paragraph above says\n * does not exist — it is the same choice with one input changed. A bump exists\n * to re-ask publishers who accepted the OLD text; production holds exactly one\n * acceptance record and it is the own, so there is nobody to re-ask and the\n * bump would buy nothing. the decision, 2026-08-22.\n *\n * The pin still had to move, for precisely the reason given above: the served\n * bytes changed, so leaving the old hash here would assert a document nobody\n * is shown. Version unchanged + pin re-captured is coherent ONLY while the\n * acceptance set is empty. The first real publisher acceptance ends that, and\n * from then on any body-text change costs a bump — see the same rule in\n * `apps/console/constants/legal-documents.ts`, where the clickwrap snapshots\n * collapsed back to `v1` on the identical argument.\n *\n * ## 2026-08-24 — `2026-08-24.1`, and why this one CANNOT be folded (AGL-1956)\n *\n * §13.3 changed twice in one sentence. The venue moved from Williamson County\n * to TRAVIS County (decided) — Williamson entered from the former\n * Jarrell residential address, while every published Aglyn address is 5900\n * Balcones Dr STE 100, Austin, TX 78731, which is Travis. And the clause cited\n * \"Terms of Service Section 19\" for governing law and venue when those live at\n * §18.6; §19 is General. A wrong cross-reference in a forum-selection clause is\n * the kind of defect that gets argued about, so it was corrected in the same\n * pass.\n *\n * Unlike 2026-08-22, this one takes the bump rather than only re-pinning, and\n * the deciding reason is mechanical rather than editorial: THIS VERSION STRING\n * IS PUBLISHED IN THE DOCUMENT. The page at {@link PUBLISHER_AGREEMENT_URL}\n * serves `Agreement version: 2026-08-24.1` in its own second line, so the\n * capture below contains it, and `publisher-agreement-version.spec.ts` asserts\n * the snapshot contains `Agreement version: ${PUBLISHER_AGREEMENT_VERSION}`.\n * Holding the constant at `2026-08-18.1` against that text would need the page\n * republished to say so, and would otherwise record a publisher as having\n * accepted `2026-08-18.1` while naming bytes that call themselves\n * `2026-08-24.1`. That is a false record of exactly the shape the pin exists\n * to prevent.\n *\n * ⚠️ THIS IS THE ONE PLACE THE CLICKWRAP ARGUMENT DOES NOT REACH. The signup\n * clickwrap folded its 2026-08-24 corrections into `v1` and did not bump\n * (`apps/console/constants/legal-documents.ts`) — decided: no v2\n * before launch. That works there because `v1` is a REPO-SIDE label: the\n * published Terms carry a \"Last updated\" date and no version string at all, so\n * the label can stay still while the text moves. Here the label is part of the\n * document a publisher reads. The two schemes are not the same kind of thing\n * and must not be reasoned about as one — that difference is the whole content\n * of this paragraph.\n *\n * On the merits it would have been a bump anyway: a forum-selection clause is\n * substance, not a typo — it names the court a publisher would have to travel\n * to. The 2026-08-22 cost argument is unchanged and still cheap, production\n * holding exactly one acceptance record which is the own.\n *\n * §8.1 and §8.3 are UNTOUCHED and were already correct: they have said Aglyn is\n * merchant of record and determines, collects and remits transaction tax since\n * 2026-08-14. The Terms of Service moved TO them in this pass (new ToS §10.7),\n * not the other way around.\n *\n * ## 2026-11-02 — `2026-11-02.1`, site starters (AGL-4049)\n *\n * The opening names site starters among the Artifacts, and §1 is now \"Site\n * Starters\": a site starter is an Artifact and everything in it is warranted\n * under §3. That replaces §1's pre-release paragraph. Its \"AS IS\" wording stays\n * in §10, and the right to change the Marketplace stays in Terms of Service\n * §5.1. §2 to §14 keep their numbers, because the repo and the native screens\n * cite them.\n *\n * The capture also carries §8.6's \"license\" spelling, which the page already\n * served after the `2026-08-24.1` pin was taken.\n */\nexport const PUBLISHER_AGREEMENT_VERSION = '2026-11-02.1'\n\nexport const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement'\n\n/**\n * The snapshot pin for the version above (AGL-1678).\n *\n * A version string is a label we control and can reuse, so on its own it\n * proves nothing about what a publisher actually read. These two values pin\n * the archived snapshot at\n * `legal/publisher-agreement/{PUBLISHER_AGREEMENT_VERSION}/marketplace-publisher-agreement.txt`\n * (beside this module), captured FROM THE LIVE PAGE after publication — the\n * same publication-first machinery as the signup clickwrap\n * (`apps/console/constants/legal-documents.ts`, AGL-1497), and deliberately a\n * PARALLEL manifest rather than an entry in `LEGAL_DOCUMENTS`: ToS §19.1 makes\n * that set the entire signup agreement, and the publisher agreement is\n * deliberately not part of it. Mixing them would widen what a signup\n * acceptance covers.\n *\n * Both values go onto every acceptance record, so a record is self-contained\n * evidence of content and later tampering with the archive is detectable\n * rather than invisible. `publisher-agreement-version.spec.ts` re-hashes the\n * snapshot, so one version string can never come to mean two different\n * documents.\n *\n * Capture method (proven byte-for-byte against the clickwrap v4 hashes before\n * this snapshot was taken): fetch the live page, walk its HTML text nodes\n * skipping script/style, trim each, drop empties, take the document's content\n * block (first line `Last updated: …` through its closing `© …` line,\n * excluding site chrome and the table of contents), join with `\\n`, and end\n * with a trailing newline. UTF-8 throughout.\n *\n * TO PUBLISH A CHANGE: publish the besigner edit first, confirm the live page\n * serves it, capture a new snapshot under the new version's directory, then\n * bump `PUBLISHER_AGREEMENT_VERSION` and these two values together, and add\n * the version's entry to `PUBLISHER_AGREEMENT_CHANGES` below. Never\n * hand-write a snapshot: it is evidence of what a publisher was shown, and a\n * snapshot of unpublished text is a false record.\n */\nexport const PUBLISHER_AGREEMENT_SHA256 =\n '3a345609a30e915be53dfeaf8e4a2c141e92a250e39cf741f8c8c0c9c764d23c'\n\n/** Byte length of the same snapshot — a cheap second check on the content. */\nexport const PUBLISHER_AGREEMENT_BYTES = 13709\n\n/**\n * Canonical document, on the operator's legal origin beside the other terms.\n *\n * Built from `LEGAL_ORIGIN` (AGL-2196), which this module already depends on:\n * `publisherAgreementIsPublished` below calls `isPublishedLegalUrl`, and that\n * accepts ONLY `LEGAL_ORIGIN`. So the gate was operator-aware while the link\n * it gates was a bare `aglyn.com` literal — meaning on a self-host install\n * with `NEXT_PUBLIC_OPERATOR_LEGAL_ORIGIN` set, the gate rejected the very URL\n * this file handed it, and every publisher was blocked from accepting. One\n * origin for both closes that, and leaves Aglyn's own URL byte-identical.\n */\nexport const PUBLISHER_AGREEMENT_URL = `${LEGAL_ORIGIN}/legal/marketplace-publisher-agreement`\n\n/**\n * Whether that document can actually be read (AGL-1660).\n *\n * It could not, from the day this gate shipped until the day this check did:\n * the URL above 404ed, and the console still rendered it as \"Read the full\n * Marketplace Publisher Agreement\" above an Accept button. An acceptance\n * collected that way is a signature on a blank page — the same\n * publication-first principle the clickwrap snapshots are built on, failing in\n * the one place the text was never published at all.\n *\n * Derived, not a second flag: it reads `PUBLISHED_LEGAL_PATHS`, so the ONE\n * edit that adds the path when the page goes live is what re-opens acceptance\n * everywhere. There is no boolean to forget to flip, and no way for the link\n * and the gate to disagree.\n */\nexport function publisherAgreementIsPublished(\n url: string = PUBLISHER_AGREEMENT_URL,\n): boolean {\n return isPublishedLegalUrl(url)\n}\n\n/**\n * What a publisher is told while the document has no page.\n *\n * Deliberately not \"try again later\" — it names the reason, because the fix is\n * ours and the publisher can do nothing about it. It must never read as though\n * accepting is something they merely have not got round to.\n */\nexport const PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE =\n `The ${PUBLISHER_AGREEMENT_TITLE} is not published yet, so there is ` +\n 'nothing here for you to read — and we will not ask you to agree to a ' +\n 'document we have not shown you. Acceptance is paused until it is ' +\n 'available, which also means marketplace publishing is paused. Nothing is ' +\n 'required of you in the meantime.'\n\n/**\n * What the agreement actually commits a publisher to.\n *\n * Shown above the accept control. A link alone is the pattern that produces\n * agreements nobody has read; these are the terms most likely to surprise\n * someone later, in the words they would need at that moment. They summarise\n * the document — they are not it, and the copy says so.\n */\nexport const PUBLISHER_AGREEMENT_POINTS: readonly {\n id: string\n label: string\n detail: string\n}[] = [\n {\n id: 'hosting-license',\n label: 'We may host, verify and distribute what you publish',\n detail:\n 'Including keeping an immutable copy of every version, inspecting its code, and showing your listing content in the marketplace and console.',\n },\n {\n id: 'warranties',\n label: 'You warrant each version as you publish it',\n detail:\n 'That you have the right to publish it, that its license is accurate and compatible, that it carries no malware or hidden telemetry, and that its documentation describes what it does with data.',\n },\n {\n id: 'immutable',\n label: 'You cannot recall code that is already installed',\n detail:\n 'Installs pin an exact version and hash. A mistake ships until an installer chooses to upgrade — publishing a new version is the only remedy you have.',\n },\n {\n id: 'revocation',\n label: 'We can disable a version everywhere, without notice',\n detail:\n 'If a version looks like a security, legal or privacy risk we stop it on every site running it, and tell you afterwards. Operating a platform that executes other people’s code requires this.',\n },\n {\n id: 'review',\n label: 'Review is a safety screen, not an endorsement',\n detail:\n 'Approval is not an audit and not a guarantee your plugin works. We may decline, delist or unsign anything, for reasons that may have nothing to do with your code.',\n },\n {\n id: 'payouts',\n label: 'On paid listings we process the sale and take a fee',\n detail:\n 'We process the purchase and pay your share into your own Stripe Connect account, less a platform fee that may change. We collect and remit sales tax on Marketplace sales; refunds, chargebacks and support on your Artifacts are yours.',\n },\n {\n id: 'indemnity',\n label: 'You indemnify us for claims arising from what you publish',\n detail:\n 'Including infringement claims and disputes with the organizations that install it.',\n },\n]\n\n/**\n * What each version changed from the one before it, in the words a publisher\n * re-accepting needs (AGL-3407).\n *\n * An org that accepted an older version is asked again, and \"the terms\n * changed\" with nothing more is a request to re-read thirteen sections to\n * find two edited clauses. Each entry names the sections that moved, read off\n * the archived snapshots beside this module (`legal/publisher-agreement/`) —\n * never written from memory of the edit, for the same reason a snapshot is\n * never hand-written.\n *\n * Oldest first. The last entry is always {@link PUBLISHER_AGREEMENT_VERSION}:\n * a bump adds its entry in the same change, and\n * `publisher-agreement-version.spec.ts` fails a bump that did not. The first\n * published version has no entry, because nothing preceded it that anyone\n * accepted.\n */\nexport const PUBLISHER_AGREEMENT_CHANGES: readonly {\n version: string\n changes: readonly string[]\n}[] = [\n {\n version: '2026-08-18.1',\n changes: [\n '§1 names the marketplace and the End User License Agreement by their current names.',\n '§3(h), new: listing conduct — what an Artifact and its listing may not claim about the platform, its plans or its prices.',\n '§8.6, new: a paid Artifact, tier or license key must be sold through the Marketplace.',\n '§13.6, new: how you may use the platform’s names and marks.',\n ],\n },\n {\n version: '2026-08-24.1',\n changes: [\n '§13.3: venue moves to Travis County, Texas, and governing law now cites Terms of Service Section 18.6.',\n ],\n },\n {\n version: '2026-11-02.1',\n changes: [\n 'Opening paragraph: site starters are among the Artifacts you can publish.',\n '§1, new: a site starter is an Artifact. Its pages, shared layout, theme and, for an AI site starter, its answers are its content, and you warrant them under §3. §1 no longer describes the Marketplace as pre-release.',\n '§8.6: a spelling correction, with no change in meaning.',\n ],\n },\n]\n\n/**\n * The changes an org has not yet accepted, oldest first.\n *\n * Versions are dated strings (`YYYY-MM-DD.n`), so they order as text. An\n * acceptance of a version this list does not name — one older than the first\n * entry — gets every entry, which is the honest answer: all of it is new to\n * them. No acceptance at all gets none, because a first acceptance is of the\n * whole document, not a set of edits.\n */\nexport function publisherAgreementChangesSince(\n acceptedVersion: string | null | undefined,\n currentVersion: string = PUBLISHER_AGREEMENT_VERSION,\n): readonly { version: string; changes: readonly string[] }[] {\n const accepted = typeof acceptedVersion === 'string' ? acceptedVersion.trim() : ''\n if (!accepted) return []\n return PUBLISHER_AGREEMENT_CHANGES.filter(\n (entry) => entry.version > accepted && entry.version <= currentVersion,\n )\n}\n\n/**\n * The org's last acceptance, as `publisherProfiles/{orgId}.publisherAgreement`\n * notes it: which version, of which exact bytes, by whom, when. Rewritten by\n * every save since AGL-4105, beside the append-only record of each one\n * ({@link PublisherAgreementAcceptanceRecord}).\n *\n * `sha256`/`bytes` (AGL-1678) pin the acceptance to the archived snapshot of\n * the text the publisher was shown. Optional because records written before\n * the pin existed carry only the version string — absence means \"accepted\n * before 2026-08-17\", not \"accepted nothing\".\n */\nexport interface PublisherAgreementAcceptance {\n version?: string\n sha256?: string\n bytes?: number\n acceptedBy?: string\n acceptedAt?: unknown\n}\n\n/**\n * Where an org stands with the agreement.\n *\n * `none` and `outdated` are deliberately different answers. \"You have never\n * agreed to anything\" and \"the terms changed since you agreed\" are different\n * situations with different copy, and collapsing them into a boolean is how\n * a re-acceptance ends up reading like a first-time setup step.\n */\nexport type PublisherAgreementState = 'none' | 'outdated' | 'current'\n\nexport function publisherAgreementState(\n acceptance: PublisherAgreementAcceptance | null | undefined,\n currentVersion: string = PUBLISHER_AGREEMENT_VERSION,\n): PublisherAgreementState {\n const accepted = acceptance?.version\n if (typeof accepted !== 'string' || !accepted.trim()) return 'none'\n return accepted === currentVersion ? 'current' : 'outdated'\n}\n\n/**\n * Whether an org's last acceptance is of the version in force.\n *\n * A note since AGL-4105, not a gate: every save agrees again on its own\n * ({@link publisherAgreementConsentRefusal}). Read by the first-party starter\n * seeding script, which writes listings without a save form.\n */\nexport function hasCurrentPublisherAgreement(\n acceptance: PublisherAgreementAcceptance | null | undefined,\n currentVersion: string = PUBLISHER_AGREEMENT_VERSION,\n): boolean {\n return publisherAgreementState(acceptance, currentVersion) === 'current'\n}\n\n/**\n * What the acceptance UI may show (AGL-1660).\n *\n * The gate lives HERE rather than in the panel, for the reason every \"check it\n * in the component\" control eventually fails: the component is not the only\n * caller. The accept route consults the same function, so a client that skips\n * the UI entirely meets the same answer.\n *\n * `documentUrl` is null, not the URL, when the document is unpublished — the\n * console reads the link target from this, so an unreadable document is\n * structurally unable to reach an href.\n */\nexport interface PublisherAgreementPresentation {\n /** The document to link, or null when there is no page to link to. */\n documentUrl: string | null\n /** Whether the accept control may be offered at all. */\n canAccept: boolean\n /** Why acceptance is unavailable, or null when it is available. */\n unavailableNotice: string | null\n}\n\nexport function publisherAgreementPresentation(\n state: PublisherAgreementState,\n published: boolean = publisherAgreementIsPublished(),\n): PublisherAgreementPresentation {\n return {\n documentUrl: published ? PUBLISHER_AGREEMENT_URL : null,\n // Already current is not \"cannot accept because unpublished\" — it is\n // nothing left to do, and the panel says so separately.\n canAccept: published && state !== 'current',\n unavailableNotice: published ? null : PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE,\n }\n}\n\n/*==========================================\n * AGREED TO ON EVERY SAVE (AGL-4105).\n *\n * Every publisher save — a profile, a listing's words, pictures, categories,\n * price or visibility, unpublishing or republishing it, a version, a\n * component, template, theme, layout, dataset schema or email, asking for the\n * Verified badge — carries {@link PublisherAgreementConsent}. The console and\n * the apps send it only while the person has ticked the box above the button,\n * and the box is unticked again after every save, so each save is its own\n * agreement. The routes refuse a write without it\n * ({@link publisherAgreementConsentRefusal}) and record who agreed, to which\n * version, for what, and from where.\n *=========================================*/\n\n/** What a save sends while its box is ticked: the version it agrees to. */\nexport interface PublisherAgreementConsent {\n version: string\n accepted: true\n}\n\n/** The box's sentence; the agreement's title in it is the link to the document. */\nexport const PUBLISHER_AGREEMENT_CONSENT_LABEL = `I agree to the ${PUBLISHER_AGREEMENT_TITLE}`\n\n/** What a save without the box ticked is told. */\nexport const PUBLISHER_AGREEMENT_CONSENT_REQUIRED = `Tick '${PUBLISHER_AGREEMENT_CONSENT_LABEL}' to save`\n\n/** What a save that agreed to an older version is told: the page was open across a change. */\nexport const PUBLISHER_AGREEMENT_CONSENT_OUTDATED =\n `The ${PUBLISHER_AGREEMENT_TITLE} changed while this was open. Reload, read ` +\n 'the current version and tick the box again to save.'\n\n/** What a save sends once its box is ticked. */\nexport function publisherAgreementConsent(\n version: string = PUBLISHER_AGREEMENT_VERSION,\n): PublisherAgreementConsent {\n return { version, accepted: true }\n}\n\n/**\n * Why a save's `agreement` does not count, or null when it does.\n *\n * `missing`: absent, not ticked, or not this shape. `outdated`: ticked for a\n * version that is no longer in force, which is a page left open across a\n * change, not a publisher who declined. `unavailable`: the document has no\n * published page, so nothing can be agreed to (AGL-1660) whatever was sent.\n */\nexport type PublisherAgreementConsentProblem = 'missing' | 'outdated' | 'unavailable'\n\nexport function publisherAgreementConsentProblem(\n raw: unknown,\n options: { currentVersion?: string; published?: boolean } = {},\n): PublisherAgreementConsentProblem | null {\n const currentVersion = options.currentVersion ?? PUBLISHER_AGREEMENT_VERSION\n const published = options.published ?? publisherAgreementIsPublished()\n if (!published) return 'unavailable'\n const consent = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>\n if (consent['accepted'] !== true) return 'missing'\n const version = typeof consent['version'] === 'string' ? consent['version'].trim() : ''\n if (!version) return 'missing'\n return version === currentVersion ? null : 'outdated'\n}\n\n/**\n * The refusal a save without a counting `agreement` gets, or null when it may\n * go ahead. One answer for every publisher route.\n *\n * 428, like the per-version attestation (AGL-969): both say \"tick the box in\n * the form in front of you\". A version from before a change is 409, the\n * conflict-with-current-state answer the retired accept route gave the same\n * mismatch, and so is an unpublished document. `agreement` is the\n * machine-readable half, for a client that wants to point at the box.\n */\nexport function publisherAgreementConsentRefusal(\n raw: unknown,\n options: { currentVersion?: string; published?: boolean } = {},\n): { status: number; body: Record<string, unknown> } | null {\n const problem = publisherAgreementConsentProblem(raw, options)\n if (!problem) return null\n const required = options.currentVersion ?? PUBLISHER_AGREEMENT_VERSION\n const agreement = { required, state: problem }\n if (problem === 'unavailable') {\n return { status: 409, body: { error: PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE, agreement } }\n }\n if (problem === 'outdated') {\n return { status: 409, body: { error: PUBLISHER_AGREEMENT_CONSENT_OUTDATED, agreement } }\n }\n return { status: 428, body: { error: PUBLISHER_AGREEMENT_CONSENT_REQUIRED, agreement } }\n}\n\n/**\n * What the box may show (AGL-1660, AGL-4105): the link, and whether it can be\n * ticked at all. The box reads its href from here, never from\n * {@link PUBLISHER_AGREEMENT_URL}, so an unpublished document cannot reach a\n * link and cannot be agreed to.\n */\nexport interface PublisherAgreementConsentPresentation {\n /** The document to link, or null when there is no page to link to. */\n documentUrl: string | null\n /** Whether the box may be ticked. */\n canAgree: boolean\n /** Why it cannot be, or null when it can. */\n unavailableNotice: string | null\n}\n\nexport function publisherAgreementConsentPresentation(\n published: boolean = publisherAgreementIsPublished(),\n): PublisherAgreementConsentPresentation {\n return {\n documentUrl: published ? PUBLISHER_AGREEMENT_URL : null,\n canAgree: published,\n unavailableNotice: published ? null : PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE,\n }\n}\n\n/**\n * Where an acceptance came from, as its record names it: one name per\n * publisher save. Closed, so a record can always be read back as an action.\n */\nexport const PUBLISHER_AGREEMENT_ACTIONS = [\n 'save-profile',\n 'publish-component',\n 'publish-layout',\n 'publish-template',\n 'publish-starter',\n 'publish-theme',\n 'publish-dataset-schema',\n 'publish-email-template',\n 'publish-email-starter',\n 'publish-plugin',\n 'update-listing',\n 'set-preview-image',\n 'remove-preview-image',\n 'set-visibility',\n 'set-published',\n 'request-verification',\n 'withdraw-verification',\n] as const\n\nexport type PublisherAgreementAction = (typeof PUBLISHER_AGREEMENT_ACTIONS)[number]\n\n/**\n * One acceptance, as `orgs/{orgId}/publisherAgreementAcceptances/{id}` holds\n * it: append-only and server-written, with the evidence a signature's audit\n * keeps (the hardware terms' acceptance is the same shape, AGL-4038) — which\n * text, by whom, when, for which save, and from which device.\n */\nexport interface PublisherAgreementAcceptanceRecord {\n version: string\n /** The archived snapshot's pin (AGL-1678), so the record names the bytes as well as the label. */\n sha256: string\n bytes: number\n orgId: string\n uid: string\n /** Whether the person was acting as staff rather than as the publisher. */\n staff: boolean\n action: PublisherAgreementAction\n /** The listing, profile or source the save wrote, or null where it has none yet. */\n targetId: string | null\n ip: string | null\n userAgent: string | null\n atMs: number\n}\n\n/** A fresh acceptance of the agreement in force. */\nexport function publisherAgreementAcceptanceRecord(input: {\n orgId: string\n uid: string\n staff?: boolean\n action: PublisherAgreementAction\n targetId?: string | null\n ip?: string | null\n userAgent?: string | null\n atMs: number\n}): PublisherAgreementAcceptanceRecord {\n const text = (value: string | null | undefined, max: number) =>\n typeof value === 'string' && value.trim() ? value.trim().slice(0, max) : null\n return {\n version: PUBLISHER_AGREEMENT_VERSION,\n sha256: PUBLISHER_AGREEMENT_SHA256,\n bytes: PUBLISHER_AGREEMENT_BYTES,\n orgId: input.orgId,\n uid: input.uid,\n staff: input.staff === true,\n action: input.action,\n targetId: text(input.targetId, 256),\n ip: text(input.ip, 100),\n userAgent: text(input.userAgent, 400),\n atMs: input.atMs,\n }\n}\n"],"names":["LEGAL_ORIGIN","isPublishedLegalUrl","PUBLISHER_AGREEMENT_VERSION","PUBLISHER_AGREEMENT_TITLE","PUBLISHER_AGREEMENT_SHA256","PUBLISHER_AGREEMENT_BYTES","PUBLISHER_AGREEMENT_URL","publisherAgreementIsPublished","url","PUBLISHER_AGREEMENT_UNAVAILABLE_NOTICE","PUBLISHER_AGREEMENT_POINTS","id","label","detail","PUBLISHER_AGREEMENT_CHANGES","version","changes","publisherAgreementChangesSince","acceptedVersion","currentVersion","accepted","trim","filter","entry","publisherAgreementState","acceptance","hasCurrentPublisherAgreement","publisherAgreementPresentation","state","published","documentUrl","canAccept","unavailableNotice","PUBLISHER_AGREEMENT_CONSENT_LABEL","PUBLISHER_AGREEMENT_CONSENT_REQUIRED","PUBLISHER_AGREEMENT_CONSENT_OUTDATED","publisherAgreementConsent","publisherAgreementConsentProblem","raw","options","consent","publisherAgreementConsentRefusal","problem","required","agreement","status","body","error","publisherAgreementConsentPresentation","canAgree","PUBLISHER_AGREEMENT_ACTIONS","publisherAgreementAcceptanceRecord","input","text","value","max","slice","sha256","bytes","orgId","uid","staff","action","targetId","ip","userAgent","atMs"],"mappings":"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"}