@aglyn/plugins-marketplace 1.0.0-beta.231 → 1.0.0-beta.232

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 (25) hide show
  1. package/package.json +14 -14
  2. package/src/lib/components/listing-content.component.js +2 -0
  3. package/src/lib/components/listing-content.component.js.map +1 -1
  4. package/src/lib/components/listing-detail-editor.component.js +1 -0
  5. package/src/lib/components/listing-detail-editor.component.js.map +1 -1
  6. package/src/lib/components/listing-detail-page.component.js +4 -0
  7. package/src/lib/components/listing-detail-page.component.js.map +1 -1
  8. package/src/lib/components/listing-review-status.component.js +1 -0
  9. package/src/lib/components/listing-review-status.component.js.map +1 -1
  10. package/src/lib/components/listing-reviews.component.js +1 -0
  11. package/src/lib/components/listing-reviews.component.js.map +1 -1
  12. package/src/lib/components/marketplace-browse.component.js +3 -0
  13. package/src/lib/components/marketplace-browse.component.js.map +1 -1
  14. package/src/lib/components/marketplace-hub.component.js +1 -0
  15. package/src/lib/components/marketplace-hub.component.js.map +1 -1
  16. package/src/lib/components/marketplace-reports-page.component.js +2 -0
  17. package/src/lib/components/marketplace-reports-page.component.js.map +1 -1
  18. package/src/lib/components/plugin-review-detail.component.js +11 -0
  19. package/src/lib/components/plugin-review-detail.component.js.map +1 -1
  20. package/src/lib/components/plugin-reviews-queue.component.js +2 -0
  21. package/src/lib/components/plugin-reviews-queue.component.js.map +1 -1
  22. package/src/lib/components/publish-plugin-form.component.js +1 -0
  23. package/src/lib/components/publish-plugin-form.component.js.map +1 -1
  24. package/src/lib/components/uninstall-impact-dialog.component.js +1 -0
  25. package/src/lib/components/uninstall-impact-dialog.component.js.map +1 -1
@@ -205,6 +205,7 @@ const FIRST_PAGES = {
205
205
  },
206
206
  children: [
207
207
  /*#__PURE__*/ _jsxs(Stack, {
208
+ useFlexGap: true,
208
209
  direction: "row",
209
210
  spacing: 1,
210
211
  sx: {
@@ -240,6 +241,7 @@ const FIRST_PAGES = {
240
241
  spacing: 3,
241
242
  children: [
242
243
  /*#__PURE__*/ _jsxs(Stack, {
244
+ useFlexGap: true,
243
245
  direction: "row",
244
246
  spacing: 1,
245
247
  sx: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/plugin-reviews-queue.component.tsx"],"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'use client'\n\nimport { PageHeaderHelp } from '@aglyn/aglyn'\nimport { AppLink, CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport ListQueryNotices, {\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport type { ListFilterClause } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport {\n Alert,\n Chip,\n MenuItem,\n Skeleton,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { reviewStatusMeaning } from '../model/plugin-review-status'\nimport {\n REVIEW_QUEUE_QUERY,\n type ReviewQueueSection,\n} from '../model/listing-query'\n\ninterface QueueRow {\n listingId: string\n displayName: string\n description: string\n license: string\n categories: string[]\n profileId: string\n reviewStatus: string\n priceUsd: number\n version: string\n hidden: boolean\n /** Private plugin (AGL-968): reviewed identically, never listed. */\n private: boolean\n /** The publisher's standing ask for the Verified badge (AGL-1217). */\n verificationRequest?: { state?: string; requestedAt?: unknown } | null\n}\n\ninterface ListedRow {\n listingId: string\n displayName: string\n reviewStatus: string\n profileId: string\n latestVersion: string\n hidden: boolean\n hiddenReason: string\n realmVersions: number\n versionCount: number\n private: boolean\n}\n\nconst STATUS_FILTERS = [\n { value: 'all', label: 'All statuses' },\n { value: 'submitted', label: 'Submitted' },\n { value: 'in_review', label: 'In review' },\n { value: 'listed', label: 'Listed' },\n { value: 'verified', label: 'Verified' },\n { value: 'hidden', label: 'Taken down' },\n]\n\n/** How the queue's clauses read in a refusal. */\nconst QUEUE_HEADERS: Readonly<Record<string, string>> = {\n reviewStatus: 'Status',\n takenDown: 'Taken down',\n}\nconst QUEUE_OPTIONS = {\n reviewStatus: STATUS_FILTERS.filter(\n (option) => option.value !== 'all' && option.value !== 'hidden',\n ),\n}\n\n/** Rows per page of each section. */\nconst QUEUE_PAGE = 50\n/** How long the search box waits for typing to stop before it asks again. */\nconst SEARCH_SETTLE_MS = 300\n\nconst NO_MORE: Record<ReviewQueueSection, boolean> = {\n queue: false,\n listed: false,\n verification: false,\n}\nconst FIRST_PAGES: Record<ReviewQueueSection, number> = {\n queue: 0,\n listed: 0,\n verification: 0,\n}\n\n/**\n * Staff marketplace review index (AGL-961).\n *\n * Scanning surface only: rows carry just enough to pick the right listing,\n * and every consequential action — verdicts, realm trust, takedown — lives\n * on the detail page. The previous version stacked all of it inline, which\n * meant the most destructive controls in the platform sat as same-weight\n * text buttons in a wall of caption text.\n *\n * The search box and the Status select are served by the route's QUERY\n * (AGL-3321): each section asks Firestore for its rows with the status and\n * the searched name word on it, so a plugin past the first hundred is found.\n * They used to be matched here over the hundred the route had read. Search\n * reads the listing name; a refusal or a one-word notice from the plan is\n * shown above the sections. Each section pages: the route reads every section\n * out to the furthest page asked plus one row, which is how a section knows\n * there is a next page (the window `usePagedCollection` reads, over a route).\n */\nexport function PluginReviewsQueue({ basePath }: { basePath: string }) {\n const { data: user } = useUser()\n const [queue, setQueue] = useState<QueueRow[]>([])\n const [listed, setListed] = useState<ListedRow[]>([])\n const [verificationRequests, setVerificationRequests] = useState<QueueRow[]>(\n [],\n )\n const [publishers, setPublishers] = useState<Record<string, string>>({})\n const [loaded, setLoaded] = useState(false)\n const [loadError, setLoadError] = useState<string | null>(null)\n const [search, setSearch] = useState('')\n const [asked, setAsked] = useState('')\n const [status, setStatus] = useState('all')\n const [pages, setPages] =\n useState<Record<ReviewQueueSection, number>>(FIRST_PAGES)\n /** Every section is read out to the furthest page any of them is on. */\n const limit = QUEUE_PAGE * (Math.max(...Object.values(pages)) + 1)\n const [more, setMore] = useState<Record<ReviewQueueSection, boolean>>(NO_MORE)\n const [refused, setRefused] = useState<\n Array<{ clause: ListFilterClause | 'search'; reason: string }>\n >([])\n const [notices, setNotices] = useState<string[]>([])\n\n // The search is asked once typing settles, not per keystroke.\n useEffect(() => {\n const timer = setTimeout(() => setAsked(search.trim()), SEARCH_SETTLE_MS)\n return () => clearTimeout(timer)\n }, [search])\n // A new question starts from the first page.\n useEffect(() => {\n setPages(FIRST_PAGES)\n }, [asked, status])\n\n const refresh = useCallback(async () => {\n const params = new URLSearchParams()\n if (asked) params.set('q', asked)\n if (status !== 'all') params.set('status', status)\n params.set('limit', String(limit))\n const suffix = params.toString()\n const response = await authorizedFetch(\n user,\n `/api/marketplace/admin/reviews${suffix ? `?${suffix}` : ''}`,\n )\n const payload = await response.json().catch(() => ({}))\n if (response.ok) {\n setLoadError(null)\n setQueue(payload?.queue ?? [])\n setListed(payload?.listed ?? [])\n setVerificationRequests(payload?.verificationRequests ?? [])\n setPublishers(payload?.publishers ?? {})\n setMore({ ...NO_MORE, ...(payload?.more ?? {}) })\n setRefused(payload?.refused ?? [])\n setNotices(payload?.notices ?? [])\n } else {\n // Named, not swallowed. An empty queue and a queue that could not be\n // read look identical, and only one of them means there is no work.\n setLoadError(\n payload?.error ?? `Loading the queue failed (${response.status})`,\n )\n }\n setLoaded(true)\n }, [user, asked, status, limit])\n\n useEffect(() => {\n if (user) void refresh()\n }, [user, refresh])\n\n const publisherName = useCallback(\n (profileId: string) => publishers[profileId] ?? profileId,\n [publishers],\n )\n\n // Every section is already what the query answered: nothing is matched\n // here, only the page on screen sliced out of the window read.\n const pageOf = <T,>(section: ReviewQueueSection, rows: T[]): T[] =>\n rows.slice(pages[section] * QUEUE_PAGE, (pages[section] + 1) * QUEUE_PAGE)\n const visibleQueue = pageOf('queue', queue)\n const visibleListed = pageOf('listed', listed)\n const visibleVerification = pageOf('verification', verificationRequests)\n const total: Record<ReviewQueueSection, number> = {\n queue: queue.length,\n listed: listed.length,\n verification: verificationRequests.length,\n }\n const filtering = asked.length > 0 || status !== 'all'\n const refusals = useMemo(\n () =>\n listQueryRefusals(refused, {\n fields: REVIEW_QUEUE_QUERY.fields,\n headers: QUEUE_HEADERS,\n options: QUEUE_OPTIONS,\n }),\n [refused],\n )\n const pager = (section: ReviewQueueSection, shown: number) => {\n const hasMore =\n total[section] > (pages[section] + 1) * QUEUE_PAGE || more[section]\n return pages[section] > 0 || hasMore ? (\n <ListPagination\n page={pages[section]}\n pageSize={QUEUE_PAGE}\n rowCount={shown}\n hasMore={hasMore}\n onPageChange={(page) =>\n setPages((previous) => ({ ...previous, [section]: page }))\n }\n />\n ) : null\n }\n\n const row = (\n key: string,\n listingId: string,\n name: string,\n profileId: string,\n chips: React.ReactNode,\n caption: string,\n ) => (\n <Stack\n key={key}\n spacing={0.25}\n sx={{\n py: 1,\n borderBottom: 1,\n borderColor: 'divider',\n '&:last-of-type': { borderBottom: 0 },\n }}\n >\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap' }}\n >\n <AppLink href={`${basePath}/${encodeURIComponent(listingId)}`}>\n <Typography variant=\"subtitle2\" component=\"span\">\n {name}\n </Typography>\n </AppLink>\n {chips}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${publisherName(profileId)} · ${caption}`}\n </Typography>\n </Stack>\n )\n\n return (\n <>\n {/*\n The staff console's own topic, anchored. A `staffPages` entry carries\n one `docsTopic` and no anchor, and the staff console page is long\n enough that landing at the top of it is the AGL-2200 shape.\n */}\n <PageHeaderHelp topic=\"staffConsole\" anchor=\"#plugin-reviews\" />\n {/*\n The staff gate is the shell's: the generic staff route renders every\n plugin page inside `StaffOnly`, which renders nothing while the claim\n resolves and 404s a non-holder. Without it a non-staff visitor was\n told \"No plugin submissions waiting for review\" — the queue fetch\n 403s and the empty result reads as good news rather than a refusal\n (AGL-760).\n */}\n <Stack spacing={3}>\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap' }}\n >\n <TextField\n size=\"small\"\n placeholder=\"Search plugin names\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n sx={{ minWidth: 320 }}\n />\n <TextField\n size=\"small\"\n select\n value={status}\n onChange={(event) => setStatus(event.target.value)}\n sx={{ minWidth: 180 }}\n >\n {STATUS_FILTERS.map((option) => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </TextField>\n </Stack>\n\n {loadError ? (\n <Alert severity=\"error\">{loadError}</Alert>\n ) : null}\n <ListQueryNotices refused={refusals} notices={notices} />\n\n {!loaded ? (\n <Stack spacing={2}>\n <Skeleton variant=\"rounded\" height={140} />\n <Skeleton variant=\"rounded\" height={200} />\n </Stack>\n ) : (\n <>\n {/* Its own card, above the review queue (AGL-1217). A\n verification request is a different question from\n \"have these bytes been read\" — it is about the\n publisher, and it is answered by a different action.\n Folded into Awaiting review it would be invisible: a\n listing whose bytes are already approved does not\n appear there at all. Hidden when empty, so it costs\n nothing on the common day. */}\n {visibleVerification.length ? (\n <CardDisplay\n header={`Verification requested (${total.verification}${more.verification ? '+' : ''})`}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#asking-to-be-verified',\n excerpt:\n 'Publishers who asked to be VERIFIED — a claim about who they are, ' +\n 'separate from reviewing any one version.',\n })}\n contentGutterX\n contentGutterY\n >\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 1 }}\n >\n {'These plugins are already live. The publisher has ' +\n 'asked us to vouch for who they are — granting adds ' +\n 'the badge and changes nothing about installability.'}\n </Typography>\n <Stack>\n {visibleVerification.map((entry) =>\n row(\n `verify-${entry.listingId}`,\n entry.listingId,\n entry.displayName,\n entry.profileId,\n <>\n <Chip\n size=\"small\"\n color=\"info\"\n label=\"Verification requested\"\n />\n <Chip\n size=\"small\"\n color={reviewStatusMeaning(entry.reviewStatus).color}\n label={reviewStatusMeaning(entry.reviewStatus).label}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`v${entry.version || '—'}`}\n />\n </>,\n 'Awaiting a verification decision',\n ),\n )}\n {pager('verification', visibleVerification.length)}\n </Stack>\n </CardDisplay>\n ) : null}\n <CardDisplay\n header={`Awaiting review (${total.queue}${more.queue ? '+' : ''})`}\n help={pluginDocsHelp('manifestAndEnvs', {\n anchor: '#review--trust-lifecycle',\n excerpt:\n 'Submissions waiting on a staff verdict. Open one to read its manifest, verifier findings and act.',\n })}\n contentGutterX\n contentGutterY\n >\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 1 }}\n >\n {'Submitted and In review are not installable by anyone.'}\n </Typography>\n {visibleQueue.length ? (\n <Stack>\n {visibleQueue.map((entry) =>\n row(\n entry.listingId,\n entry.listingId,\n entry.displayName,\n entry.profileId,\n <>\n <Chip\n size=\"small\"\n color={reviewStatusMeaning(entry.reviewStatus).color}\n label={reviewStatusMeaning(entry.reviewStatus).label}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`v${entry.version || '—'}`}\n />\n {/* Same bar, smaller audience (AGL-968/995).\n Worth flagging so a reviewer knows the\n blast radius is one workspace — never so\n they review it more loosely. */}\n {entry.private ? (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Private\"\n />\n ) : null}\n {/* A private plugin has no marketplace listing\n page, so \"no license\" is not a finding. */}\n {entry.license || entry.private ? null : (\n <Chip\n size=\"small\"\n color=\"warning\"\n label=\"No license\"\n />\n )}\n </>,\n entry.priceUsd > 0 ? `$${entry.priceUsd}` : 'Free',\n ),\n )}\n {pager('queue', visibleQueue.length)}\n </Stack>\n ) : (\n <Alert severity={filtering ? 'info' : 'success'}>\n {filtering\n ? 'No submissions match this filter.'\n : 'No plugin submissions waiting for review.'}\n </Alert>\n )}\n </CardDisplay>\n\n <CardDisplay\n header={`Listed plugins (${total.listed}${more.listed ? '+' : ''})`}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#review-what-happens-after-you-publish',\n excerpt:\n 'Listings already installable. Listing is the step that makes a ' +\n 'version reachable from Browse.',\n })}\n contentGutterX\n contentGutterY\n >\n {/* Listed vs Verified is the distinction reviewers get\n wrong (AGL-966): both are LIVE. Verified only adds a\n badge — it does not change who can install. */}\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 1 }}\n >\n {'Both states are live — installable by every workspace. ' +\n 'Verified additionally carries the reviewed badge on ' +\n 'its listing page; it does not change installability. ' +\n // The sentence above is false for a private row\n // (AGL-968/995), and it sits directly over the rows\n // it would misdescribe.\n 'Rows marked Private are the exception: approved and ' +\n 'live, but only for the org that published them.'}\n </Typography>\n {visibleListed.length ? (\n <Stack>\n {visibleListed.map((entry) =>\n row(\n entry.listingId,\n entry.listingId,\n entry.displayName,\n entry.profileId,\n <>\n <Chip\n size=\"small\"\n color={reviewStatusMeaning(entry.reviewStatus).color}\n label={reviewStatusMeaning(entry.reviewStatus).label}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`v${entry.latestVersion || '—'}`}\n />\n {entry.private ? (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Private\"\n />\n ) : null}\n {entry.realmVersions ? (\n <Chip\n size=\"small\"\n color=\"success\"\n label={`${entry.realmVersions} realm-trusted`}\n />\n ) : null}\n {entry.hidden ? (\n <Chip\n size=\"small\"\n color=\"error\"\n label=\"Taken down\"\n />\n ) : null}\n </>,\n `${entry.versionCount} version${\n entry.versionCount === 1 ? '' : 's'\n }${entry.hidden && entry.hiddenReason ? ` · ${entry.hiddenReason}` : ''}`,\n ),\n )}\n {pager('listed', visibleListed.length)}\n </Stack>\n ) : (\n <Alert severity=\"info\">\n {filtering\n ? 'No listed plugins match this filter.'\n : 'No listed plugins yet.'}\n </Alert>\n )}\n </CardDisplay>\n </>\n )}\n </Stack>\n </>\n )\n}\n\nexport default PluginReviewsQueue\n"],"names":["PageHeaderHelp","AppLink","CardDisplay","ListPagination","ListQueryNotices","listQueryRefusals","Alert","Chip","MenuItem","Skeleton","Stack","TextField","Typography","useCallback","useEffect","useMemo","useState","useUser","authorizedFetch","pluginDocsHelp","reviewStatusMeaning","REVIEW_QUEUE_QUERY","STATUS_FILTERS","value","label","QUEUE_HEADERS","reviewStatus","takenDown","QUEUE_OPTIONS","filter","option","QUEUE_PAGE","SEARCH_SETTLE_MS","NO_MORE","queue","listed","verification","FIRST_PAGES","PluginReviewsQueue","basePath","data","user","setQueue","setListed","verificationRequests","setVerificationRequests","publishers","setPublishers","loaded","setLoaded","loadError","setLoadError","search","setSearch","asked","setAsked","status","setStatus","pages","setPages","limit","Math","max","Object","values","more","setMore","refused","setRefused","notices","setNotices","timer","setTimeout","trim","clearTimeout","refresh","params","URLSearchParams","set","String","suffix","toString","response","payload","json","catch","ok","error","publisherName","profileId","pageOf","section","rows","slice","visibleQueue","visibleListed","visibleVerification","total","length","filtering","refusals","fields","headers","options","pager","shown","hasMore","page","pageSize","rowCount","onPageChange","previous","row","key","listingId","name","chips","caption","spacing","sx","py","borderBottom","borderColor","direction","alignItems","flexWrap","href","encodeURIComponent","variant","component","color","topic","anchor","size","placeholder","onChange","event","target","minWidth","select","map","severity","height","header","help","excerpt","contentGutterX","contentGutterY","display","mb","entry","displayName","version","private","license","priceUsd","latestVersion","realmVersions","hidden","versionCount","hiddenReason"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/plugin-reviews-queue.component.tsx"],"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'use client'\n\nimport { PageHeaderHelp } from '@aglyn/aglyn'\nimport { AppLink, CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport ListQueryNotices, {\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport type { ListFilterClause } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport {\n Alert,\n Chip,\n MenuItem,\n Skeleton,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { reviewStatusMeaning } from '../model/plugin-review-status'\nimport {\n REVIEW_QUEUE_QUERY,\n type ReviewQueueSection,\n} from '../model/listing-query'\n\ninterface QueueRow {\n listingId: string\n displayName: string\n description: string\n license: string\n categories: string[]\n profileId: string\n reviewStatus: string\n priceUsd: number\n version: string\n hidden: boolean\n /** Private plugin (AGL-968): reviewed identically, never listed. */\n private: boolean\n /** The publisher's standing ask for the Verified badge (AGL-1217). */\n verificationRequest?: { state?: string; requestedAt?: unknown } | null\n}\n\ninterface ListedRow {\n listingId: string\n displayName: string\n reviewStatus: string\n profileId: string\n latestVersion: string\n hidden: boolean\n hiddenReason: string\n realmVersions: number\n versionCount: number\n private: boolean\n}\n\nconst STATUS_FILTERS = [\n { value: 'all', label: 'All statuses' },\n { value: 'submitted', label: 'Submitted' },\n { value: 'in_review', label: 'In review' },\n { value: 'listed', label: 'Listed' },\n { value: 'verified', label: 'Verified' },\n { value: 'hidden', label: 'Taken down' },\n]\n\n/** How the queue's clauses read in a refusal. */\nconst QUEUE_HEADERS: Readonly<Record<string, string>> = {\n reviewStatus: 'Status',\n takenDown: 'Taken down',\n}\nconst QUEUE_OPTIONS = {\n reviewStatus: STATUS_FILTERS.filter(\n (option) => option.value !== 'all' && option.value !== 'hidden',\n ),\n}\n\n/** Rows per page of each section. */\nconst QUEUE_PAGE = 50\n/** How long the search box waits for typing to stop before it asks again. */\nconst SEARCH_SETTLE_MS = 300\n\nconst NO_MORE: Record<ReviewQueueSection, boolean> = {\n queue: false,\n listed: false,\n verification: false,\n}\nconst FIRST_PAGES: Record<ReviewQueueSection, number> = {\n queue: 0,\n listed: 0,\n verification: 0,\n}\n\n/**\n * Staff marketplace review index (AGL-961).\n *\n * Scanning surface only: rows carry just enough to pick the right listing,\n * and every consequential action — verdicts, realm trust, takedown — lives\n * on the detail page. The previous version stacked all of it inline, which\n * meant the most destructive controls in the platform sat as same-weight\n * text buttons in a wall of caption text.\n *\n * The search box and the Status select are served by the route's QUERY\n * (AGL-3321): each section asks Firestore for its rows with the status and\n * the searched name word on it, so a plugin past the first hundred is found.\n * They used to be matched here over the hundred the route had read. Search\n * reads the listing name; a refusal or a one-word notice from the plan is\n * shown above the sections. Each section pages: the route reads every section\n * out to the furthest page asked plus one row, which is how a section knows\n * there is a next page (the window `usePagedCollection` reads, over a route).\n */\nexport function PluginReviewsQueue({ basePath }: { basePath: string }) {\n const { data: user } = useUser()\n const [queue, setQueue] = useState<QueueRow[]>([])\n const [listed, setListed] = useState<ListedRow[]>([])\n const [verificationRequests, setVerificationRequests] = useState<QueueRow[]>(\n [],\n )\n const [publishers, setPublishers] = useState<Record<string, string>>({})\n const [loaded, setLoaded] = useState(false)\n const [loadError, setLoadError] = useState<string | null>(null)\n const [search, setSearch] = useState('')\n const [asked, setAsked] = useState('')\n const [status, setStatus] = useState('all')\n const [pages, setPages] =\n useState<Record<ReviewQueueSection, number>>(FIRST_PAGES)\n /** Every section is read out to the furthest page any of them is on. */\n const limit = QUEUE_PAGE * (Math.max(...Object.values(pages)) + 1)\n const [more, setMore] = useState<Record<ReviewQueueSection, boolean>>(NO_MORE)\n const [refused, setRefused] = useState<\n Array<{ clause: ListFilterClause | 'search'; reason: string }>\n >([])\n const [notices, setNotices] = useState<string[]>([])\n\n // The search is asked once typing settles, not per keystroke.\n useEffect(() => {\n const timer = setTimeout(() => setAsked(search.trim()), SEARCH_SETTLE_MS)\n return () => clearTimeout(timer)\n }, [search])\n // A new question starts from the first page.\n useEffect(() => {\n setPages(FIRST_PAGES)\n }, [asked, status])\n\n const refresh = useCallback(async () => {\n const params = new URLSearchParams()\n if (asked) params.set('q', asked)\n if (status !== 'all') params.set('status', status)\n params.set('limit', String(limit))\n const suffix = params.toString()\n const response = await authorizedFetch(\n user,\n `/api/marketplace/admin/reviews${suffix ? `?${suffix}` : ''}`,\n )\n const payload = await response.json().catch(() => ({}))\n if (response.ok) {\n setLoadError(null)\n setQueue(payload?.queue ?? [])\n setListed(payload?.listed ?? [])\n setVerificationRequests(payload?.verificationRequests ?? [])\n setPublishers(payload?.publishers ?? {})\n setMore({ ...NO_MORE, ...(payload?.more ?? {}) })\n setRefused(payload?.refused ?? [])\n setNotices(payload?.notices ?? [])\n } else {\n // Named, not swallowed. An empty queue and a queue that could not be\n // read look identical, and only one of them means there is no work.\n setLoadError(\n payload?.error ?? `Loading the queue failed (${response.status})`,\n )\n }\n setLoaded(true)\n }, [user, asked, status, limit])\n\n useEffect(() => {\n if (user) void refresh()\n }, [user, refresh])\n\n const publisherName = useCallback(\n (profileId: string) => publishers[profileId] ?? profileId,\n [publishers],\n )\n\n // Every section is already what the query answered: nothing is matched\n // here, only the page on screen sliced out of the window read.\n const pageOf = <T,>(section: ReviewQueueSection, rows: T[]): T[] =>\n rows.slice(pages[section] * QUEUE_PAGE, (pages[section] + 1) * QUEUE_PAGE)\n const visibleQueue = pageOf('queue', queue)\n const visibleListed = pageOf('listed', listed)\n const visibleVerification = pageOf('verification', verificationRequests)\n const total: Record<ReviewQueueSection, number> = {\n queue: queue.length,\n listed: listed.length,\n verification: verificationRequests.length,\n }\n const filtering = asked.length > 0 || status !== 'all'\n const refusals = useMemo(\n () =>\n listQueryRefusals(refused, {\n fields: REVIEW_QUEUE_QUERY.fields,\n headers: QUEUE_HEADERS,\n options: QUEUE_OPTIONS,\n }),\n [refused],\n )\n const pager = (section: ReviewQueueSection, shown: number) => {\n const hasMore =\n total[section] > (pages[section] + 1) * QUEUE_PAGE || more[section]\n return pages[section] > 0 || hasMore ? (\n <ListPagination\n page={pages[section]}\n pageSize={QUEUE_PAGE}\n rowCount={shown}\n hasMore={hasMore}\n onPageChange={(page) =>\n setPages((previous) => ({ ...previous, [section]: page }))\n }\n />\n ) : null\n }\n\n const row = (\n key: string,\n listingId: string,\n name: string,\n profileId: string,\n chips: React.ReactNode,\n caption: string,\n ) => (\n <Stack\n key={key}\n spacing={0.25}\n sx={{\n py: 1,\n borderBottom: 1,\n borderColor: 'divider',\n '&:last-of-type': { borderBottom: 0 },\n }}\n >\n <Stack\n useFlexGap\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap' }}\n >\n <AppLink href={`${basePath}/${encodeURIComponent(listingId)}`}>\n <Typography variant=\"subtitle2\" component=\"span\">\n {name}\n </Typography>\n </AppLink>\n {chips}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${publisherName(profileId)} · ${caption}`}\n </Typography>\n </Stack>\n )\n\n return (\n <>\n {/*\n The staff console's own topic, anchored. A `staffPages` entry carries\n one `docsTopic` and no anchor, and the staff console page is long\n enough that landing at the top of it is the AGL-2200 shape.\n */}\n <PageHeaderHelp topic=\"staffConsole\" anchor=\"#plugin-reviews\" />\n {/*\n The staff gate is the shell's: the generic staff route renders every\n plugin page inside `StaffOnly`, which renders nothing while the claim\n resolves and 404s a non-holder. Without it a non-staff visitor was\n told \"No plugin submissions waiting for review\" — the queue fetch\n 403s and the empty result reads as good news rather than a refusal\n (AGL-760).\n */}\n <Stack spacing={3}>\n <Stack\n useFlexGap\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap' }}\n >\n <TextField\n size=\"small\"\n placeholder=\"Search plugin names\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n sx={{ minWidth: 320 }}\n />\n <TextField\n size=\"small\"\n select\n value={status}\n onChange={(event) => setStatus(event.target.value)}\n sx={{ minWidth: 180 }}\n >\n {STATUS_FILTERS.map((option) => (\n <MenuItem key={option.value} value={option.value}>\n {option.label}\n </MenuItem>\n ))}\n </TextField>\n </Stack>\n\n {loadError ? (\n <Alert severity=\"error\">{loadError}</Alert>\n ) : null}\n <ListQueryNotices refused={refusals} notices={notices} />\n\n {!loaded ? (\n <Stack spacing={2}>\n <Skeleton variant=\"rounded\" height={140} />\n <Skeleton variant=\"rounded\" height={200} />\n </Stack>\n ) : (\n <>\n {/* Its own card, above the review queue (AGL-1217). A\n verification request is a different question from\n \"have these bytes been read\" — it is about the\n publisher, and it is answered by a different action.\n Folded into Awaiting review it would be invisible: a\n listing whose bytes are already approved does not\n appear there at all. Hidden when empty, so it costs\n nothing on the common day. */}\n {visibleVerification.length ? (\n <CardDisplay\n header={`Verification requested (${total.verification}${more.verification ? '+' : ''})`}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#asking-to-be-verified',\n excerpt:\n 'Publishers who asked to be VERIFIED — a claim about who they are, ' +\n 'separate from reviewing any one version.',\n })}\n contentGutterX\n contentGutterY\n >\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 1 }}\n >\n {'These plugins are already live. The publisher has ' +\n 'asked us to vouch for who they are — granting adds ' +\n 'the badge and changes nothing about installability.'}\n </Typography>\n <Stack>\n {visibleVerification.map((entry) =>\n row(\n `verify-${entry.listingId}`,\n entry.listingId,\n entry.displayName,\n entry.profileId,\n <>\n <Chip\n size=\"small\"\n color=\"info\"\n label=\"Verification requested\"\n />\n <Chip\n size=\"small\"\n color={reviewStatusMeaning(entry.reviewStatus).color}\n label={reviewStatusMeaning(entry.reviewStatus).label}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`v${entry.version || '—'}`}\n />\n </>,\n 'Awaiting a verification decision',\n ),\n )}\n {pager('verification', visibleVerification.length)}\n </Stack>\n </CardDisplay>\n ) : null}\n <CardDisplay\n header={`Awaiting review (${total.queue}${more.queue ? '+' : ''})`}\n help={pluginDocsHelp('manifestAndEnvs', {\n anchor: '#review--trust-lifecycle',\n excerpt:\n 'Submissions waiting on a staff verdict. Open one to read its manifest, verifier findings and act.',\n })}\n contentGutterX\n contentGutterY\n >\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 1 }}\n >\n {'Submitted and In review are not installable by anyone.'}\n </Typography>\n {visibleQueue.length ? (\n <Stack>\n {visibleQueue.map((entry) =>\n row(\n entry.listingId,\n entry.listingId,\n entry.displayName,\n entry.profileId,\n <>\n <Chip\n size=\"small\"\n color={reviewStatusMeaning(entry.reviewStatus).color}\n label={reviewStatusMeaning(entry.reviewStatus).label}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`v${entry.version || '—'}`}\n />\n {/* Same bar, smaller audience (AGL-968/995).\n Worth flagging so a reviewer knows the\n blast radius is one workspace — never so\n they review it more loosely. */}\n {entry.private ? (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Private\"\n />\n ) : null}\n {/* A private plugin has no marketplace listing\n page, so \"no license\" is not a finding. */}\n {entry.license || entry.private ? null : (\n <Chip\n size=\"small\"\n color=\"warning\"\n label=\"No license\"\n />\n )}\n </>,\n entry.priceUsd > 0 ? `$${entry.priceUsd}` : 'Free',\n ),\n )}\n {pager('queue', visibleQueue.length)}\n </Stack>\n ) : (\n <Alert severity={filtering ? 'info' : 'success'}>\n {filtering\n ? 'No submissions match this filter.'\n : 'No plugin submissions waiting for review.'}\n </Alert>\n )}\n </CardDisplay>\n\n <CardDisplay\n header={`Listed plugins (${total.listed}${more.listed ? '+' : ''})`}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#review-what-happens-after-you-publish',\n excerpt:\n 'Listings already installable. Listing is the step that makes a ' +\n 'version reachable from Browse.',\n })}\n contentGutterX\n contentGutterY\n >\n {/* Listed vs Verified is the distinction reviewers get\n wrong (AGL-966): both are LIVE. Verified only adds a\n badge — it does not change who can install. */}\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ display: 'block', mb: 1 }}\n >\n {'Both states are live — installable by every workspace. ' +\n 'Verified additionally carries the reviewed badge on ' +\n 'its listing page; it does not change installability. ' +\n // The sentence above is false for a private row\n // (AGL-968/995), and it sits directly over the rows\n // it would misdescribe.\n 'Rows marked Private are the exception: approved and ' +\n 'live, but only for the org that published them.'}\n </Typography>\n {visibleListed.length ? (\n <Stack>\n {visibleListed.map((entry) =>\n row(\n entry.listingId,\n entry.listingId,\n entry.displayName,\n entry.profileId,\n <>\n <Chip\n size=\"small\"\n color={reviewStatusMeaning(entry.reviewStatus).color}\n label={reviewStatusMeaning(entry.reviewStatus).label}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`v${entry.latestVersion || '—'}`}\n />\n {entry.private ? (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Private\"\n />\n ) : null}\n {entry.realmVersions ? (\n <Chip\n size=\"small\"\n color=\"success\"\n label={`${entry.realmVersions} realm-trusted`}\n />\n ) : null}\n {entry.hidden ? (\n <Chip\n size=\"small\"\n color=\"error\"\n label=\"Taken down\"\n />\n ) : null}\n </>,\n `${entry.versionCount} version${\n entry.versionCount === 1 ? '' : 's'\n }${entry.hidden && entry.hiddenReason ? ` · ${entry.hiddenReason}` : ''}`,\n ),\n )}\n {pager('listed', visibleListed.length)}\n </Stack>\n ) : (\n <Alert severity=\"info\">\n {filtering\n ? 'No listed plugins match this filter.'\n : 'No listed plugins yet.'}\n </Alert>\n )}\n </CardDisplay>\n </>\n )}\n </Stack>\n </>\n )\n}\n\nexport default PluginReviewsQueue\n"],"names":["PageHeaderHelp","AppLink","CardDisplay","ListPagination","ListQueryNotices","listQueryRefusals","Alert","Chip","MenuItem","Skeleton","Stack","TextField","Typography","useCallback","useEffect","useMemo","useState","useUser","authorizedFetch","pluginDocsHelp","reviewStatusMeaning","REVIEW_QUEUE_QUERY","STATUS_FILTERS","value","label","QUEUE_HEADERS","reviewStatus","takenDown","QUEUE_OPTIONS","filter","option","QUEUE_PAGE","SEARCH_SETTLE_MS","NO_MORE","queue","listed","verification","FIRST_PAGES","PluginReviewsQueue","basePath","data","user","setQueue","setListed","verificationRequests","setVerificationRequests","publishers","setPublishers","loaded","setLoaded","loadError","setLoadError","search","setSearch","asked","setAsked","status","setStatus","pages","setPages","limit","Math","max","Object","values","more","setMore","refused","setRefused","notices","setNotices","timer","setTimeout","trim","clearTimeout","refresh","params","URLSearchParams","set","String","suffix","toString","response","payload","json","catch","ok","error","publisherName","profileId","pageOf","section","rows","slice","visibleQueue","visibleListed","visibleVerification","total","length","filtering","refusals","fields","headers","options","pager","shown","hasMore","page","pageSize","rowCount","onPageChange","previous","row","key","listingId","name","chips","caption","spacing","sx","py","borderBottom","borderColor","useFlexGap","direction","alignItems","flexWrap","href","encodeURIComponent","variant","component","color","topic","anchor","size","placeholder","onChange","event","target","minWidth","select","map","severity","height","header","help","excerpt","contentGutterX","contentGutterY","display","mb","entry","displayName","version","private","license","priceUsd","latestVersion","realmVersions","hidden","versionCount","hiddenReason"],"mappings":"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"}
@@ -807,6 +807,7 @@ const draftKey = (orgId, listingId)=>`aglyn.publish-plugin.draft.${orgId}${listi
807
807
  onChange: ()=>toggleAttestation(item.id)
808
808
  }),
809
809
  label: /*#__PURE__*/ _jsxs(Stack, {
810
+ useFlexGap: true,
810
811
  direction: "row",
811
812
  spacing: 1,
812
813
  sx: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/publish-plugin-form.component.tsx"],"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'use client'\n\nimport {\n formatMediaRef,\n offeredPluginVersion,\n useMediaPicker,\n type PluginRevocation,\n} from '@aglyn/aglyn'\nimport {\n isBelowMarketplacePriceFloor,\n marketplacePriceCostNote,\n marketplacePriceFloorHint,\n} from '../model/listing-price-floor'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Button,\n Checkbox,\n Chip,\n FormControlLabel,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n missingAttestationSubjects,\n PUBLISHER_ATTESTATION,\n requiredAttestationIds,\n} from '../model/publisher-attestation'\nimport {\n MarkdownField,\n type MarkdownFieldHandle,\n} from '@aglyn/aglyn-markdown-editor'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { inheritedMediaAlt } from '@aglyn/aglyn/app-utils/media-metadata'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { listingPath } from '../model/marketplace-paths'\nimport usePublisherAgreementGate from './use-publisher-agreement-gate'\n\n// Mirrors the server taxonomy; the server re-validates (the console cannot\n// import the marketplace plugin's model — scope:app may not reach aglyn:addons).\nconst LISTING_CATEGORIES = [\n 'analytics',\n 'automation',\n 'commerce',\n 'communication',\n 'content',\n 'design',\n 'forms',\n 'integrations',\n 'marketing',\n 'productivity',\n 'seo',\n 'security',\n] as const\n\n// Mirrors `validateListingContent`'s URL rule, which is what the publish\n// route enforces — this only saves a round trip (AGL-1076).\nconst isHttpsUrl = (value: string) =>\n /^https:\\/\\/[^\\s]+$/.test(value.trim()) && value.trim().length <= 500\n\n/** Base64-encode file bytes without a data: prefix. */\nasync function fileToBase64(file: File): Promise<string> {\n const buffer = await file.arrayBuffer()\n let binary = ''\n const bytes = new Uint8Array(buffer)\n for (let i = 0; i < bytes.length; i += 1)\n binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\n/**\n * Everything the draft can hold.\n *\n * The bundle File is deliberately absent. A File cannot be serialized, and\n * a draft that silently restores every field except the one that decides\n * what actually ships is worse than no draft — the publisher would believe\n * they were republishing the bytes they left with. It is re-chosen, and the\n * page says so rather than pretending otherwise.\n */\ninterface PublishDraft {\n manifestText: string\n displayName: string\n description: string\n category: string\n changelog: string\n priceUsd: string\n readme: string\n license: string\n repositoryUrl: string\n visibility: 'public' | 'private'\n attested: string[]\n}\n\n/**\n * One verifier finding as the publish API returns it (AGL-1091). Declared\n * locally rather than imported: the shared type lives in the server barrel,\n * which carries the parser this form must never ship to a browser.\n */\ninterface PublishProblem {\n level?: string\n message: string\n /** Which check produced it (AGL-1087) — absent on older responses. */\n check?: string\n}\n\nconst EMPTY_DRAFT: PublishDraft = {\n manifestText: '',\n displayName: '',\n description: '',\n category: '',\n changelog: '',\n priceUsd: '0',\n readme: '',\n license: '',\n repositoryUrl: '',\n visibility: 'public',\n attested: [],\n}\n\n// Scoped per listing (AGL-1008): an update draft and a new-listing draft\n// are different submissions, and sharing one key would let a half-written\n// update reappear on top of a first publish.\nconst draftKey = (orgId: string, listingId?: string) =>\n `aglyn.publish-plugin.draft.${orgId}${listingId ? `.${listingId}` : ''}`\n\n/**\n * Read the stored draft, during render.\n *\n * Deliberately NOT an effect. Restoring in one effect while a second effect\n * persists on every change is a race that Strict Mode wins: React\n * double-invokes effects in development, so the persist pass writes the\n * still-empty state back over storage BEFORE the restore's `setDraft` has\n * applied, and the re-run then restores the emptiness it just wrote. The\n * draft looked correct in jsdom (no Strict Mode) and silently vanished in\n * the browser. A read during initialization has no ordering to lose.\n */\nfunction readDraft(orgId: string, listingId?: string): PublishDraft {\n if (typeof window === 'undefined' || !orgId) return EMPTY_DRAFT\n try {\n const stored = window.localStorage.getItem(draftKey(orgId, listingId))\n if (!stored) return EMPTY_DRAFT\n return { ...EMPTY_DRAFT, ...(JSON.parse(stored) as Partial<PublishDraft>) }\n } catch {\n // A corrupt draft is not worth failing the page over.\n return EMPTY_DRAFT\n }\n}\n\n/**\n * Fill an update's form from the listing it is bound to (AGL-1008).\n *\n * A saved draft wins over the listing on every field: the listing is where\n * you START from, and overwriting an edit someone made and reloaded away\n * from would be the same data loss the draft exists to prevent.\n *\n * `changelog` is deliberately never seeded. It is the one field that\n * describes THIS version, and carrying the previous version's text forward\n * is how a changelog ends up describing a release it has nothing to do\n * with — which the AGL-969 attestation then asks the publisher to confirm.\n */\nfunction seedDraft(\n draft: PublishDraft,\n listing: UpdateTargetListing | null | undefined,\n): PublishDraft {\n if (!listing?.$id) return draft\n const seeded = { ...draft }\n const carry = <K extends keyof PublishDraft>(\n key: K,\n value: string | undefined,\n ) => {\n if (seeded[key] === EMPTY_DRAFT[key] && value) {\n seeded[key] = value as PublishDraft[K]\n }\n }\n carry('displayName', listing.displayName)\n carry('description', listing.description)\n carry('category', listing.categories?.[0] ?? listing.category)\n carry('readme', listing.readme)\n carry('license', listing.license)\n carry('repositoryUrl', listing.repositoryUrl)\n if (seeded.priceUsd === EMPTY_DRAFT.priceUsd && listing.priceUsd) {\n seeded.priceUsd = String(listing.priceUsd)\n }\n // Visibility is set on FIRST publish only — the server ignores it on a\n // version bump — so reflect what the listing actually is rather than\n // offering a choice that would be silently discarded.\n if (listing.visibility === 'private') seeded.visibility = 'private'\n return seeded\n}\n\n/**\n * Whether a stored draft is worth telling anyone about.\n *\n * The persist effect runs on mount, so an untouched form writes its\n * starting state straight back — and without this the NEXT first visit\n * would announce \"picked up where you left off\" over a form nobody had\n * typed in. A restore notice that fires when nothing was restored is how a\n * publisher learns to ignore it, which is expensive on the one visit it\n * matters.\n *\n * Compared against the BASELINE rather than the empty draft: on an update\n * the baseline is the listing's own content (AGL-1008), so an untouched\n * update form is not a resumed one.\n */\nfunction draftDiffersFrom(\n draft: Partial<PublishDraft>,\n baseline: PublishDraft,\n): boolean {\n return (Object.keys(EMPTY_DRAFT) as Array<keyof PublishDraft>).some((key) => {\n const value = draft[key]\n if (value === undefined) return false\n if (Array.isArray(value)) {\n const other = baseline[key]\n return (\n !Array.isArray(other) ||\n value.length !== other.length ||\n value.some((entry, index) => entry !== other[index])\n )\n }\n return value !== baseline[key]\n })\n}\n\n/** The listing an update is bound to (AGL-1008), as the console reads it. */\nexport interface UpdateTargetListing {\n $id: string\n displayName?: string\n pluginId?: string\n latestVersion?: string | number\n latestApprovedVersion?: string | number\n description?: string\n category?: string\n categories?: string[]\n readme?: string\n license?: string\n repositoryUrl?: string\n priceUsd?: number\n visibility?: string\n}\n\nexport interface PublishPluginFormProps {\n orgId: string\n /**\n * Where the marketplace hub is mounted under this organization, from the\n * shell (AGL-3080). The listing the publish lands on hangs beneath it; it\n * replaced an org slug and the console's route table, which a plugin may\n * not import.\n */\n basePath: string\n /**\n * Set when publishing a NEW VERSION of an existing listing (AGL-1008).\n * The server still decides whether a submission is an update, from\n * `profileId` + the manifest id — this only pre-binds the form so the\n * publisher is not retyping a listing they already own, and so the page\n * can say what is about to happen.\n */\n listing?: UpdateTargetListing | null\n /**\n * The listing's kill switch (AGL-2368), so `liveVersion` below can answer\n * \"what installs today\" rather than \"what review last approved\". Those are\n * different questions and `latestApprovedVersion` only answers the second.\n */\n revocation?: PluginRevocation | null\n}\n\n/**\n * The plugin publish form (AGL-1078), as a page.\n *\n * It was a modal. A publish is the most consequential thing a publisher\n * does — it puts executable code in front of every workspace that installs\n * it — and it had no URL to link or resume, no draft, and no room, which is\n * why the AGL-969 checklist ended up below the publish button where it had\n * to be scrolled past to be read.\n *\n * Same server contract: this posts the identical body to\n * `/api/marketplace/publish-plugin`. What changed is the container, and what\n * the container makes possible — sections, a draft that survives a reload,\n * server problems shown against the field that caused them, and somewhere\n * to go afterwards.\n */\nexport function PublishPluginForm(props: PublishPluginFormProps) {\n const { orgId, basePath, listing, revocation } = props\n const isUpdate = Boolean(listing?.$id)\n const { data: user } = useUser()\n const router = useRouter()\n const { enqueueSnackbar } = useSnackbar()\n const [busy, setBusy] = useState(false)\n\n const bundleRef = useRef<HTMLInputElement>(null)\n const manifestRef = useRef<HTMLInputElement>(null)\n const [bundleFile, setBundleFile] = useState<File | null>(null)\n const [manifestFile, setManifestFile] = useState<File | null>(null)\n // Inline README images come from the shared DAM, like everywhere else.\n const readmeEditorRef = useRef<MarkdownFieldHandle | null>(null)\n /*\n * The console's media library, opened through the picker context rather\n * than by mounting its dialog (AGL-3080): the library is coupled to the\n * org and the session, which a plugin has no way to reach, and the console\n * provides `pickMedia` around every plugin page for exactly this.\n */\n const { pickMedia } = useMediaPicker()\n const insertReadmeImage = useCallback(async () => {\n const media = await pickMedia?.({ kind: 'image' })\n if (!media) return\n // A reference, not the origin-absolute CDN URL (AGL-1705) — the same\n // switch the listing detail editor's README body makes, and for the\n // reason established there: this markdown renders only in the console,\n // through the one `marketplaceListing` slot, so nothing was relying on\n // the baked-in origin. The URL stays the fallback for a free-tier asset,\n // which is minted no `cdnPath` and so has no reference to name.\n const src = formatMediaRef(media.mediaScope, media.mediaId) ?? media.url\n // The alt was a hardcoded '' (AGL-1896). Same reasoning as the listing\n // detail editor: no alt prompt exists on this surface, and a\n // markdown-lite image row's alt is fixed at insert time — so the asset's\n // own alt is the only description that could ever land here, and '' was\n // otherwise permanent.\n if (src)\n readmeEditorRef.current?.insertImage(\n inheritedMediaAlt({ assetAlt: media.alt }) ?? '',\n src,\n )\n }, [pickMedia])\n // What an untouched form looks like: empty for a first publish, the\n // listing's own content for an update (AGL-1008).\n const baseline = seedDraft(EMPTY_DRAFT, listing)\n const [draft, setDraft] = useState<PublishDraft>(() =>\n seedDraft(readDraft(orgId, listing?.$id), listing),\n )\n const [draftRestored, setDraftRestored] = useState(() =>\n draftDiffersFrom(\n seedDraft(readDraft(orgId, listing?.$id), listing),\n seedDraft(EMPTY_DRAFT, listing),\n ),\n )\n\n // Server-side problems, held against the field that caused them (AGL-1078)\n // instead of thrown at a snackbar that is gone before it is read. Cleared\n // on every submit so a fixed problem stops being shown as one.\n //\n // Objects, not strings (AGL-1091): the verifier has always answered with\n // `{level, message, check}` and this held `string[]`, so rendering a\n // rejection threw \"objects are not valid as a React child\" and the error\n // boundary ate the very card that was supposed to explain the rejection.\n // Normalized on arrival so a plain string from anywhere else still reads.\n const [problems, setProblems] = useState<PublishProblem[]>([])\n const [missingAttestations, setMissingAttestations] = useState<string[]>([])\n const [agreementProblem, setAgreementProblem] = useState('')\n // The publisher agreement (AGL-3407), asked for HERE rather than on the\n // Publisher Profile tab: offered as the form opens when the org's\n // acceptance is missing or stale, and presented again if the publish is\n // refused for it — accepting sends the same bundle and fields again.\n const agreement = usePublisherAgreementGate({ orgId, offer: true })\n const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({})\n\n const set = <K extends keyof PublishDraft>(key: K) =>\n (value: PublishDraft[K]) =>\n setDraft((current) => ({ ...current, [key]: value }))\n\n // Written back on every change — one small JSON blob, and the only thing\n // that makes a reload safe. Safe to run on the first pass now that the\n // restore happens during initialization: the value it writes IS the\n // restored one, so there is nothing left to clobber.\n useEffect(() => {\n if (!orgId) return\n try {\n window.localStorage.setItem(\n draftKey(orgId, listing?.$id),\n JSON.stringify(draft),\n )\n } catch {\n // Storage full or blocked — the form still works, it just won't survive.\n }\n }, [orgId, listing?.$id, draft])\n\n const clearDraft = useCallback(() => {\n try {\n window.localStorage.removeItem(draftKey(orgId, listing?.$id))\n } catch {\n // Nothing to do; the next publish overwrites it anyway.\n }\n }, [orgId, listing?.$id])\n\n const toggleAttestation = (id: string) =>\n setDraft((current) => ({\n ...current,\n attested: current.attested.includes(id)\n ? current.attested.filter((entry) => entry !== id)\n : [...current.attested, id],\n }))\n\n /**\n * What this page blocks on locally.\n *\n * On a first publish the changelog item is `updateOnly` and this form\n * genuinely cannot know whether the manifest id already has a listing —\n * the server answers that and names it in a 428. Demanding a changelog\n * attestation from a first-time publisher would be the worse failure: an\n * item that does not apply teaches people to tick without reading.\n *\n * Bound to a listing (AGL-1008) we DO know, so the update-only item is\n * asked here rather than arriving as a refusal after the upload.\n */\n const unattested = requiredAttestationIds(isUpdate).filter(\n (id) => !draft.attested.includes(id),\n )\n const unfilledSubjects = missingAttestationSubjects(\n { repositoryUrl: draft.repositoryUrl },\n isUpdate,\n )\n const repositoryInvalid =\n Boolean(draft.repositoryUrl.trim()) && !isHttpsUrl(draft.repositoryUrl)\n\n /**\n * The manifest id typed or pasted so far, if it parses.\n *\n * Only used to catch the one way a pre-bound update silently isn't one:\n * the server decides update-vs-new from `profileId` + the manifest id, so\n * a bundle whose id does not match this listing creates a SECOND listing\n * while the page says \"new version\". Cheap to notice here; impossible to\n * undo afterwards, because a published version is immutable.\n */\n const typedManifestId = (() => {\n const raw = draft.manifestText.trim()\n if (!raw) return ''\n try {\n const parsed = JSON.parse(raw) as { id?: unknown }\n return typeof parsed?.id === 'string' ? parsed.id : ''\n } catch {\n return ''\n }\n })()\n const manifestIdMismatch = Boolean(\n isUpdate && typedManifestId && listing?.pluginId &&\n typedManifestId !== listing.pluginId,\n )\n\n /**\n * What is serving customers right now (AGL-2368).\n *\n * This prints as \"v{X} is what installs today\", which is an INSTALL claim,\n * and it was reading a REVIEW verdict — the kill switch does not clear\n * `latestApprovedVersion`, so a publisher whose live version had been\n * stopped was told it was still installing, on the page they had come to\n * to ship its replacement.\n *\n * Falls through to nothing rather than to `latestVersion` when the offer is\n * revoked: the alert's other branch already says \"nothing installs until a\n * reviewer approves it\", which is the truth in that state.\n */\n const liveVersion = String(\n offeredPluginVersion(listing, revocation) ?? listing?.latestVersion ?? '',\n )\n\n const readManifest = async (): Promise<Record<string, unknown> | null> => {\n // A pasted manifest wins; otherwise read the chosen file.\n const raw = draft.manifestText.trim()\n ? draft.manifestText\n : manifestFile\n ? await manifestFile.text()\n : ''\n if (!raw) return null\n try {\n const parsed = JSON.parse(raw)\n return parsed && typeof parsed === 'object' ? parsed : null\n } catch {\n return null\n }\n }\n\n const submit = async () => {\n setProblems([])\n setMissingAttestations([])\n setAgreementProblem('')\n setFieldErrors({})\n if (!bundleFile) {\n setFieldErrors({ bundle: 'Choose a plugin bundle (.js) to upload.' })\n return\n }\n const manifest = await readManifest()\n if (!manifest) {\n setFieldErrors({\n manifest: 'Add a valid manifest (JSON) — id, name, version and entry.',\n })\n return\n }\n setBusy(true)\n try {\n const bundle = await fileToBase64(bundleFile)\n // Serialized once: a retry after the agreement is accepted sends the\n // bytes this attempt did, not whatever the form holds by then.\n const body = JSON.stringify({\n orgId,\n bundle,\n manifest,\n displayName:\n draft.displayName.trim() ||\n String((manifest as { name?: unknown }).name ?? '').trim(),\n description: draft.description.trim(),\n category: draft.category || undefined,\n changelog: draft.changelog.trim(),\n // A private plugin has no buyers — its only audience already owns\n // it — so it publishes free regardless of what the field held\n // before the publisher switched visibility.\n priceUsd:\n draft.visibility === 'private'\n ? 0\n : Math.max(0, Math.round(Number(draft.priceUsd) || 0)),\n visibility: draft.visibility,\n attestation: draft.attested,\n ...(draft.readme.trim() ? { readme: draft.readme.trim() } : {}),\n ...(draft.license.trim() ? { license: draft.license.trim() } : {}),\n ...(draft.repositoryUrl.trim()\n ? { repositoryUrl: draft.repositoryUrl.trim() }\n : {}),\n })\n const { response, payload, declined } = await agreement.send(() =>\n authorizedFetch(user, '/api/marketplace/publish-plugin', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n }),\n )\n if (!response.ok) {\n if (Array.isArray(payload?.problems)) {\n setProblems(\n payload.problems.map((problem: unknown) =>\n typeof problem === 'string'\n ? { message: problem }\n : {\n level: String(\n (problem as PublishProblem)?.level ?? 'error',\n ),\n message: String((problem as PublishProblem)?.message ?? ''),\n check: (problem as PublishProblem)?.check\n ? String((problem as PublishProblem).check)\n : undefined,\n },\n ),\n )\n }\n if (Array.isArray(payload?.missingAttestations)) {\n setMissingAttestations(payload.missingAttestations)\n }\n // The agreement was presented and closed without accepting\n // (AGL-3407). Held as an alert with the way back to it, not a toast:\n // the dialog already said why, and the form keeps everything.\n if (declined) {\n return void setAgreementProblem(String(payload.error ?? ''))\n }\n // A rejected subject names its field (AGL-1076), so put the message\n // where the value is rather than in a banner about a form.\n if (Array.isArray(payload?.missingAttestationSubjects)) {\n setFieldErrors(\n Object.fromEntries(\n payload.missingAttestationSubjects.map((field: string) => [\n field,\n String(payload.error ?? 'Required'),\n ]),\n ),\n )\n }\n return void enqueueSnackbar(payload?.error ?? 'Publish failed', {\n variant: response.status === 501 ? 'info' : 'error',\n allowDuplicate: true,\n })\n }\n // Somewhere to go (AGL-1078). The dialog closed onto the panel it\n // opened from, which said nothing about what had just happened; the\n // listing shows the version now queued for review.\n clearDraft()\n enqueueSnackbar(\n `Published v${payload?.version ?? '1'} — it is queued for review`,\n { variant: 'success' },\n )\n router.push(listingPath(basePath, String(payload?.listingId ?? '')))\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }\n\n // A price under the floor is refused by the publish route (AGL-2343), so the\n // button holds rather than letting a publisher upload a bundle and read the\n // minimum off a 400. A private plugin has no price at all — its field is\n // disabled and sends 0 — so it can never be blocked by this.\n const priceBelowFloor =\n draft.visibility !== 'private' &&\n isBelowMarketplacePriceFloor(draft.priceUsd)\n\n const blocked =\n busy ||\n !bundleFile ||\n unattested.length > 0 ||\n unfilledSubjects.length > 0 ||\n repositoryInvalid ||\n manifestIdMismatch ||\n priceBelowFloor\n\n return (\n <Stack spacing={2}>\n {isUpdate ? (\n /* AGL-1008. The mechanism was always right — same profileId plus\n manifest id bumps the listing, the new version enters review as\n pending, and the approved one keeps installing (AGL-966). The UI\n never told that story, so updating read like creating a second\n listing. */\n <Alert severity=\"info\">\n <Typography variant=\"subtitle2\">\n {`New version of ${listing?.displayName ?? 'your plugin'}`}\n </Typography>\n <Typography variant=\"caption\" component=\"div\">\n {liveVersion\n ? `v${liveVersion} is what installs today. It keeps installing ` +\n 'until a reviewer approves this one — nobody is upgraded ' +\n 'onto unreviewed code, and nothing you publish here can ' +\n 'change a version already installed.'\n : 'This version enters review. Nothing installs until a ' +\n 'reviewer approves it.'}\n </Typography>\n </Alert>\n ) : (\n <Alert severity=\"info\">\n {'Plugins publish sandboxed — they run isolated and can’t touch ' +\n 'site data directly. A reviewer verifies and signs yours before ' +\n 'it can run trusted.'}\n </Alert>\n )}\n\n {manifestIdMismatch ? (\n <Alert severity=\"warning\">\n {`This manifest says \"${typedManifestId}\", but ${\n listing?.displayName ?? 'this listing'\n } publishes \"${listing?.pluginId}\". Publishing it would create a ` +\n 'separate new listing rather than a new version of this one.'}\n </Alert>\n ) : null}\n\n {draftRestored ? (\n <Alert severity=\"info\" onClose={() => setDraftRestored(false)}>\n {'Picked up where you left off. Your bundle and manifest file are ' +\n 'not saved — choose them again before publishing.'}\n </Alert>\n ) : null}\n\n {agreementProblem ? (\n <Alert\n severity=\"warning\"\n action={\n <Button color=\"inherit\" size=\"small\" onClick={agreement.review}>\n {'Review the agreement'}\n </Button>\n }\n >\n {agreementProblem}\n </Alert>\n ) : null}\n {agreement.dialog}\n\n <CardDisplay\n header={isUpdate ? 'The new bundle and manifest' : 'Bundle and manifest'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#publishing-a-version',\n excerpt:\n 'One self-contained bundle plus its manifest — verified before ' +\n 'it is stored, and content-addressed once it is.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <Stack spacing={0.5}>\n <Typography variant=\"subtitle2\">{'Bundle (.js)'}</Typography>\n <input\n ref={bundleRef}\n type=\"file\"\n accept=\".js,text/javascript,application/javascript\"\n hidden\n onChange={(event) =>\n setBundleFile(event.target.files?.[0] ?? null)\n }\n />\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button size=\"small\" onClick={() => bundleRef.current?.click()}>\n {'Choose bundle'}\n </Button>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {bundleFile?.name ?? 'No file chosen'}\n </Typography>\n </Stack>\n <Typography\n variant=\"caption\"\n color={fieldErrors['bundle'] ? 'error.main' : 'text.secondary'}\n >\n {fieldErrors['bundle'] ??\n 'One self-contained bundle. It’s parsed and checked before ' +\n 'publishing — forbidden APIs, size, and every network ' +\n 'call against the origins your manifest declares.'}\n </Typography>\n </Stack>\n\n <Stack spacing={0.5}>\n <Typography variant=\"subtitle2\">\n {'Manifest (JSON: id, name, version, entry)'}\n </Typography>\n <input\n ref={manifestRef}\n type=\"file\"\n accept=\".json,application/json\"\n hidden\n onChange={(event) =>\n setManifestFile(event.target.files?.[0] ?? null)\n }\n />\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button size=\"small\" onClick={() => manifestRef.current?.click()}>\n {'Choose manifest.json'}\n </Button>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {manifestFile?.name ?? 'or paste below'}\n </Typography>\n </Stack>\n <TextField\n placeholder='{ \"id\": \"acme-widget\", \"name\": \"Widget\", \"version\": \"1.0.0\", \"entry\": \"index.js\" }'\n value={draft.manifestText}\n onChange={(event) => set('manifestText')(event.target.value)}\n size=\"small\"\n multiline\n minRows={4}\n fullWidth\n error={Boolean(fieldErrors['manifest'])}\n helperText={fieldErrors['manifest'] ?? ' '}\n />\n </Stack>\n\n {problems.length ? (\n <Alert\n severity={\n problems.some((problem) => problem.level !== 'warning')\n ? 'error'\n : 'warning'\n }\n >\n <Typography variant=\"subtitle2\">\n {problems.some((problem) => problem.level !== 'warning')\n ? 'Bundle failed verification'\n : 'Bundle verified, with things to check'}\n </Typography>\n <ul style={{ margin: '4px 0 0', paddingLeft: 18 }}>\n {problems.map((problem, index) => (\n <li key={`${problem.check ?? 'problem'}-${index}`}>\n <Typography variant=\"caption\">\n {problem.check ? `${problem.check}: ` : ''}\n {problem.message}\n </Typography>\n </li>\n ))}\n </ul>\n </Alert>\n ) : null}\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header={'Listing'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#authoring-your-listing',\n excerpt:\n 'What a reviewer reads first and a buyer reads before running ' +\n 'third-party code.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <TextField\n label=\"Listing name\"\n helperText=\"Defaults to the manifest name\"\n value={draft.displayName}\n onChange={(event) => set('displayName')(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"Description\"\n helperText=\"The one-line summary on browse cards\"\n value={draft.description}\n onChange={(event) => set('description')(event.target.value)}\n size=\"small\"\n multiline\n minRows={2}\n />\n <TextField\n select\n label=\"Category\"\n value={draft.category}\n onChange={(event) => set('category')(event.target.value)}\n size=\"small\"\n >\n <MenuItem value=\"\">{'None'}</MenuItem>\n {LISTING_CATEGORIES.map((entry) => (\n <MenuItem key={entry} value={entry}>\n {entry}\n </MenuItem>\n ))}\n </TextField>\n {/* The same editor the listing detail page uses (AGL-1080). The\n first time a publisher writes the document reviewers read\n first used to get the worst tool we have, and the second time\n the good one — for the same field. The AGL-969 attestation\n made that worse by asking them to confirm the README\n documents what data the plugin handles, in a box too small to\n see whether it does. */}\n <MarkdownField\n label=\"README\"\n value={draft.readme}\n onChange={set('readme')}\n onPickImageFromMedia={insertReadmeImage}\n editorRef={(handle) => {\n readmeEditorRef.current = handle\n }}\n helperText={\n 'Shown on your listing page — what it does, how to configure ' +\n 'it, and what it reads, stores or sends. Reviewers and ' +\n 'cautious buyers read this first.'\n }\n />\n {/* The only field that exclusively concerns updates (AGL-1080).\n It was a single line labelled `Changelog` and nothing else,\n presented as an equal peer of Category — while AGL-969 attests\n to it and AGL-976 builds the listing's changelog tab out of\n it. The helper names both audiences, because \"what changed\"\n means something different to each. */}\n <TextField\n label=\"Changelog\"\n placeholder=\"Fixed the timer drift on Safari; added a compact layout\"\n helperText={\n isUpdate\n ? 'The field that matters most on an update. Two audiences: ' +\n 'the reviewer, comparing these bytes against ' +\n (liveVersion ? `v${liveVersion}` : 'the last approved ' +\n 'version') +\n ', and every installer deciding whether to move off the ' +\n 'version they are running.'\n : 'Two audiences: the reviewer, comparing this version ' +\n 'against the last approved one, and every installer who ' +\n 'reads it on your listing’s changelog tab before ' +\n 'updating. On a first version there is nothing to compare ' +\n 'against — say what the plugin does instead, or leave it.'\n }\n value={draft.changelog}\n onChange={(event) => set('changelog')(event.target.value)}\n size=\"small\"\n multiline\n minRows={3}\n />\n {/* AGL-1076: the subject of the repository attestation below. */}\n <TextField\n label=\"Repository URL\"\n placeholder=\"https://github.com/acme/widget\"\n required\n error={repositoryInvalid || Boolean(fieldErrors['repositoryUrl'])}\n helperText={\n repositoryInvalid\n ? 'Must be an https URL.'\n : (fieldErrors['repositoryUrl'] ??\n 'The source for this bundle. A reviewer opens it first — ' +\n 'it is what the repository confirmation below is about.')\n }\n value={draft.repositoryUrl}\n onChange={(event) => set('repositoryUrl')(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"License\"\n placeholder=\"MIT\"\n helperText=\"Short label, e.g. MIT or Apache-2.0\"\n value={draft.license}\n onChange={(event) => set('license')(event.target.value)}\n size=\"small\"\n />\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header={'Who can install it, and for how much'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#private-plugins',\n excerpt:\n 'Private is a choice about audience, not about trust — it takes ' +\n 'the identical review path.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {/* Private plugins (AGL-968/992): deliberately worded as an\n AUDIENCE choice — private is not a faster lane, and the caption\n says so, because \"skip the queue\" is the reading it would\n otherwise invite. */}\n <TextField\n select\n label=\"Who can install this\"\n value={draft.visibility}\n // Set on FIRST publish only — the server ignores it on a version\n // bump (AGL-968), so offering the choice here would be a control\n // that silently does nothing. Change it from the listing.\n disabled={isUpdate}\n onChange={(event) =>\n set('visibility')(event.target.value as 'public' | 'private')\n }\n size=\"small\"\n helperText={\n isUpdate\n ? 'Set when the listing was created. Change it from the ' +\n 'listing — a new version never changes who can install it.'\n :\n draft.visibility === 'private'\n ? 'Private plugins take the same review path — same ' +\n 'queue, same checklist, same verifier, same signature ' +\n 'for realm trust. They are never listed in the ' +\n 'marketplace, and only your sites can install them.'\n : 'Listed in the marketplace for every workspace once a ' +\n 'reviewer approves it.'\n }\n >\n <MenuItem value=\"public\">\n {'Anyone — publish to the marketplace'}\n </MenuItem>\n <MenuItem value=\"private\">\n {'Only this organization — private plugin'}\n </MenuItem>\n </TextField>\n <TextField\n label=\"Price (USD)\"\n // A private plugin has no buyers, and a price on one would only\n // send the publisher through Stripe onboarding to sell to\n // themselves.\n disabled={draft.visibility === 'private'}\n // The minimum price (AGL-2343), from the same functions every other\n // publish form reads, so no two forms can quote different figures\n // at a publisher — and stated up front rather than only on refusal.\n error={priceBelowFloor}\n helperText={\n draft.visibility === 'private'\n ? 'Private plugins are free — nobody else can install them.'\n : (marketplacePriceCostNote(draft.priceUsd) ??\n marketplacePriceFloorHint(\n 'Paid listings need payouts set up.',\n ))\n }\n type=\"number\"\n value={draft.visibility === 'private' ? '0' : draft.priceUsd}\n onChange={(event) => set('priceUsd')(event.target.value)}\n size=\"small\"\n />\n </Stack>\n </CardDisplay>\n\n {/* The checklist last, in full view of the publish button (AGL-969 /\n AGL-1078). In the dialog it sat below the button and had to be\n scrolled past to be seen at all. Every item is a statement only the\n publisher can make. */}\n <CardDisplay\n header={'Before you publish'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#before-you-publish',\n excerpt:\n 'Recorded against this exact bundle, with your name and the ' +\n 'date, and shown to the reviewer.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Recorded against this exact bundle, with your name and the ' +\n 'date, and shown to the reviewer. Republishing the same ' +\n 'version number asks again — the bytes changed.'}\n </Typography>\n {missingAttestations.length ? (\n <Alert severity=\"warning\">\n {'This plugin already has a published version, so the ' +\n 'highlighted item applies too.'}\n </Alert>\n ) : null}\n {PUBLISHER_ATTESTATION.map((item) => {\n const flagged = missingAttestations.includes(item.id)\n return (\n <Stack key={item.id} spacing={0.25}>\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n checked={draft.attested.includes(item.id)}\n disabled={busy}\n onChange={() => toggleAttestation(item.id)}\n />\n }\n label={\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap' }}\n >\n <Typography\n variant=\"body2\"\n color={flagged ? 'warning.main' : undefined}\n >\n {item.label}\n </Typography>\n {item.updateOnly ? (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Updates only\"\n />\n ) : null}\n </Stack>\n }\n />\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ pl: 4 }}\n >\n {item.detail}\n </Typography>\n </Stack>\n )\n })}\n </Stack>\n </CardDisplay>\n\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => void submit()}\n disabled={blocked}\n >\n {busy\n ? 'Publishing…'\n : !bundleFile\n ? 'Choose a bundle'\n : unattested.length\n ? `Confirm ${unattested.length} more`\n : unfilledSubjects.length || repositoryInvalid\n ? 'Add a repository URL'\n : isUpdate\n ? 'Publish new version'\n : draft.visibility === 'private'\n ? 'Publish privately'\n : 'Publish plugin'}\n </Button>\n <Button\n disabled={busy}\n onClick={() => {\n clearDraft()\n setDraft(baseline)\n setBundleFile(null)\n setManifestFile(null)\n setDraftRestored(false)\n }}\n >\n {'Discard draft'}\n </Button>\n </Stack>\n\n </Stack>\n )\n}\n\nPublishPluginForm.displayName = 'PublishPluginForm'\n\nexport default PublishPluginForm\n"],"names":["formatMediaRef","offeredPluginVersion","useMediaPicker","isBelowMarketplacePriceFloor","marketplacePriceCostNote","marketplacePriceFloorHint","CardDisplay","useSnackbar","Alert","Button","Checkbox","Chip","FormControlLabel","MenuItem","Stack","TextField","Typography","useRouter","useCallback","useEffect","useRef","useState","useUser","missingAttestationSubjects","PUBLISHER_ATTESTATION","requiredAttestationIds","MarkdownField","pluginDocsHelp","inheritedMediaAlt","authorizedFetch","listingPath","usePublisherAgreementGate","LISTING_CATEGORIES","isHttpsUrl","value","test","trim","length","fileToBase64","file","buffer","arrayBuffer","binary","bytes","Uint8Array","i","String","fromCharCode","btoa","EMPTY_DRAFT","manifestText","displayName","description","category","changelog","priceUsd","readme","license","repositoryUrl","visibility","attested","draftKey","orgId","listingId","readDraft","window","stored","localStorage","getItem","JSON","parse","seedDraft","draft","listing","$id","seeded","carry","key","categories","draftDiffersFrom","baseline","Object","keys","some","undefined","Array","isArray","other","entry","index","PublishPluginForm","props","fieldErrors","basePath","revocation","isUpdate","Boolean","data","user","router","enqueueSnackbar","busy","setBusy","bundleRef","manifestRef","bundleFile","setBundleFile","manifestFile","setManifestFile","readmeEditorRef","pickMedia","insertReadmeImage","media","kind","src","mediaScope","mediaId","url","current","insertImage","assetAlt","alt","setDraft","draftRestored","setDraftRestored","problems","setProblems","missingAttestations","setMissingAttestations","agreementProblem","setAgreementProblem","agreement","offer","setFieldErrors","set","setItem","stringify","clearDraft","removeItem","toggleAttestation","id","includes","filter","unattested","unfilledSubjects","repositoryInvalid","typedManifestId","raw","parsed","manifestIdMismatch","pluginId","liveVersion","latestVersion","readManifest","text","submit","bundle","manifest","body","name","Math","max","round","Number","attestation","response","payload","declined","send","method","headers","ok","map","problem","message","level","check","error","fromEntries","field","variant","status","allowDuplicate","version","push","console","priceBelowFloor","blocked","spacing","severity","component","onClose","action","color","size","onClick","review","dialog","header","help","anchor","excerpt","contentGutterX","contentGutterY","input","ref","type","accept","hidden","onChange","event","target","files","direction","sx","alignItems","click","noWrap","placeholder","multiline","minRows","fullWidth","helperText","ul","style","margin","paddingLeft","li","label","select","onPickImageFromMedia","editorRef","handle","required","disabled","item","flagged","control","checked","flexWrap","updateOnly","pl","detail"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/publish-plugin-form.component.tsx"],"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'use client'\n\nimport {\n formatMediaRef,\n offeredPluginVersion,\n useMediaPicker,\n type PluginRevocation,\n} from '@aglyn/aglyn'\nimport {\n isBelowMarketplacePriceFloor,\n marketplacePriceCostNote,\n marketplacePriceFloorHint,\n} from '../model/listing-price-floor'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Button,\n Checkbox,\n Chip,\n FormControlLabel,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n missingAttestationSubjects,\n PUBLISHER_ATTESTATION,\n requiredAttestationIds,\n} from '../model/publisher-attestation'\nimport {\n MarkdownField,\n type MarkdownFieldHandle,\n} from '@aglyn/aglyn-markdown-editor'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { inheritedMediaAlt } from '@aglyn/aglyn/app-utils/media-metadata'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { listingPath } from '../model/marketplace-paths'\nimport usePublisherAgreementGate from './use-publisher-agreement-gate'\n\n// Mirrors the server taxonomy; the server re-validates (the console cannot\n// import the marketplace plugin's model — scope:app may not reach aglyn:addons).\nconst LISTING_CATEGORIES = [\n 'analytics',\n 'automation',\n 'commerce',\n 'communication',\n 'content',\n 'design',\n 'forms',\n 'integrations',\n 'marketing',\n 'productivity',\n 'seo',\n 'security',\n] as const\n\n// Mirrors `validateListingContent`'s URL rule, which is what the publish\n// route enforces — this only saves a round trip (AGL-1076).\nconst isHttpsUrl = (value: string) =>\n /^https:\\/\\/[^\\s]+$/.test(value.trim()) && value.trim().length <= 500\n\n/** Base64-encode file bytes without a data: prefix. */\nasync function fileToBase64(file: File): Promise<string> {\n const buffer = await file.arrayBuffer()\n let binary = ''\n const bytes = new Uint8Array(buffer)\n for (let i = 0; i < bytes.length; i += 1)\n binary += String.fromCharCode(bytes[i])\n return btoa(binary)\n}\n\n/**\n * Everything the draft can hold.\n *\n * The bundle File is deliberately absent. A File cannot be serialized, and\n * a draft that silently restores every field except the one that decides\n * what actually ships is worse than no draft — the publisher would believe\n * they were republishing the bytes they left with. It is re-chosen, and the\n * page says so rather than pretending otherwise.\n */\ninterface PublishDraft {\n manifestText: string\n displayName: string\n description: string\n category: string\n changelog: string\n priceUsd: string\n readme: string\n license: string\n repositoryUrl: string\n visibility: 'public' | 'private'\n attested: string[]\n}\n\n/**\n * One verifier finding as the publish API returns it (AGL-1091). Declared\n * locally rather than imported: the shared type lives in the server barrel,\n * which carries the parser this form must never ship to a browser.\n */\ninterface PublishProblem {\n level?: string\n message: string\n /** Which check produced it (AGL-1087) — absent on older responses. */\n check?: string\n}\n\nconst EMPTY_DRAFT: PublishDraft = {\n manifestText: '',\n displayName: '',\n description: '',\n category: '',\n changelog: '',\n priceUsd: '0',\n readme: '',\n license: '',\n repositoryUrl: '',\n visibility: 'public',\n attested: [],\n}\n\n// Scoped per listing (AGL-1008): an update draft and a new-listing draft\n// are different submissions, and sharing one key would let a half-written\n// update reappear on top of a first publish.\nconst draftKey = (orgId: string, listingId?: string) =>\n `aglyn.publish-plugin.draft.${orgId}${listingId ? `.${listingId}` : ''}`\n\n/**\n * Read the stored draft, during render.\n *\n * Deliberately NOT an effect. Restoring in one effect while a second effect\n * persists on every change is a race that Strict Mode wins: React\n * double-invokes effects in development, so the persist pass writes the\n * still-empty state back over storage BEFORE the restore's `setDraft` has\n * applied, and the re-run then restores the emptiness it just wrote. The\n * draft looked correct in jsdom (no Strict Mode) and silently vanished in\n * the browser. A read during initialization has no ordering to lose.\n */\nfunction readDraft(orgId: string, listingId?: string): PublishDraft {\n if (typeof window === 'undefined' || !orgId) return EMPTY_DRAFT\n try {\n const stored = window.localStorage.getItem(draftKey(orgId, listingId))\n if (!stored) return EMPTY_DRAFT\n return { ...EMPTY_DRAFT, ...(JSON.parse(stored) as Partial<PublishDraft>) }\n } catch {\n // A corrupt draft is not worth failing the page over.\n return EMPTY_DRAFT\n }\n}\n\n/**\n * Fill an update's form from the listing it is bound to (AGL-1008).\n *\n * A saved draft wins over the listing on every field: the listing is where\n * you START from, and overwriting an edit someone made and reloaded away\n * from would be the same data loss the draft exists to prevent.\n *\n * `changelog` is deliberately never seeded. It is the one field that\n * describes THIS version, and carrying the previous version's text forward\n * is how a changelog ends up describing a release it has nothing to do\n * with — which the AGL-969 attestation then asks the publisher to confirm.\n */\nfunction seedDraft(\n draft: PublishDraft,\n listing: UpdateTargetListing | null | undefined,\n): PublishDraft {\n if (!listing?.$id) return draft\n const seeded = { ...draft }\n const carry = <K extends keyof PublishDraft>(\n key: K,\n value: string | undefined,\n ) => {\n if (seeded[key] === EMPTY_DRAFT[key] && value) {\n seeded[key] = value as PublishDraft[K]\n }\n }\n carry('displayName', listing.displayName)\n carry('description', listing.description)\n carry('category', listing.categories?.[0] ?? listing.category)\n carry('readme', listing.readme)\n carry('license', listing.license)\n carry('repositoryUrl', listing.repositoryUrl)\n if (seeded.priceUsd === EMPTY_DRAFT.priceUsd && listing.priceUsd) {\n seeded.priceUsd = String(listing.priceUsd)\n }\n // Visibility is set on FIRST publish only — the server ignores it on a\n // version bump — so reflect what the listing actually is rather than\n // offering a choice that would be silently discarded.\n if (listing.visibility === 'private') seeded.visibility = 'private'\n return seeded\n}\n\n/**\n * Whether a stored draft is worth telling anyone about.\n *\n * The persist effect runs on mount, so an untouched form writes its\n * starting state straight back — and without this the NEXT first visit\n * would announce \"picked up where you left off\" over a form nobody had\n * typed in. A restore notice that fires when nothing was restored is how a\n * publisher learns to ignore it, which is expensive on the one visit it\n * matters.\n *\n * Compared against the BASELINE rather than the empty draft: on an update\n * the baseline is the listing's own content (AGL-1008), so an untouched\n * update form is not a resumed one.\n */\nfunction draftDiffersFrom(\n draft: Partial<PublishDraft>,\n baseline: PublishDraft,\n): boolean {\n return (Object.keys(EMPTY_DRAFT) as Array<keyof PublishDraft>).some((key) => {\n const value = draft[key]\n if (value === undefined) return false\n if (Array.isArray(value)) {\n const other = baseline[key]\n return (\n !Array.isArray(other) ||\n value.length !== other.length ||\n value.some((entry, index) => entry !== other[index])\n )\n }\n return value !== baseline[key]\n })\n}\n\n/** The listing an update is bound to (AGL-1008), as the console reads it. */\nexport interface UpdateTargetListing {\n $id: string\n displayName?: string\n pluginId?: string\n latestVersion?: string | number\n latestApprovedVersion?: string | number\n description?: string\n category?: string\n categories?: string[]\n readme?: string\n license?: string\n repositoryUrl?: string\n priceUsd?: number\n visibility?: string\n}\n\nexport interface PublishPluginFormProps {\n orgId: string\n /**\n * Where the marketplace hub is mounted under this organization, from the\n * shell (AGL-3080). The listing the publish lands on hangs beneath it; it\n * replaced an org slug and the console's route table, which a plugin may\n * not import.\n */\n basePath: string\n /**\n * Set when publishing a NEW VERSION of an existing listing (AGL-1008).\n * The server still decides whether a submission is an update, from\n * `profileId` + the manifest id — this only pre-binds the form so the\n * publisher is not retyping a listing they already own, and so the page\n * can say what is about to happen.\n */\n listing?: UpdateTargetListing | null\n /**\n * The listing's kill switch (AGL-2368), so `liveVersion` below can answer\n * \"what installs today\" rather than \"what review last approved\". Those are\n * different questions and `latestApprovedVersion` only answers the second.\n */\n revocation?: PluginRevocation | null\n}\n\n/**\n * The plugin publish form (AGL-1078), as a page.\n *\n * It was a modal. A publish is the most consequential thing a publisher\n * does — it puts executable code in front of every workspace that installs\n * it — and it had no URL to link or resume, no draft, and no room, which is\n * why the AGL-969 checklist ended up below the publish button where it had\n * to be scrolled past to be read.\n *\n * Same server contract: this posts the identical body to\n * `/api/marketplace/publish-plugin`. What changed is the container, and what\n * the container makes possible — sections, a draft that survives a reload,\n * server problems shown against the field that caused them, and somewhere\n * to go afterwards.\n */\nexport function PublishPluginForm(props: PublishPluginFormProps) {\n const { orgId, basePath, listing, revocation } = props\n const isUpdate = Boolean(listing?.$id)\n const { data: user } = useUser()\n const router = useRouter()\n const { enqueueSnackbar } = useSnackbar()\n const [busy, setBusy] = useState(false)\n\n const bundleRef = useRef<HTMLInputElement>(null)\n const manifestRef = useRef<HTMLInputElement>(null)\n const [bundleFile, setBundleFile] = useState<File | null>(null)\n const [manifestFile, setManifestFile] = useState<File | null>(null)\n // Inline README images come from the shared DAM, like everywhere else.\n const readmeEditorRef = useRef<MarkdownFieldHandle | null>(null)\n /*\n * The console's media library, opened through the picker context rather\n * than by mounting its dialog (AGL-3080): the library is coupled to the\n * org and the session, which a plugin has no way to reach, and the console\n * provides `pickMedia` around every plugin page for exactly this.\n */\n const { pickMedia } = useMediaPicker()\n const insertReadmeImage = useCallback(async () => {\n const media = await pickMedia?.({ kind: 'image' })\n if (!media) return\n // A reference, not the origin-absolute CDN URL (AGL-1705) — the same\n // switch the listing detail editor's README body makes, and for the\n // reason established there: this markdown renders only in the console,\n // through the one `marketplaceListing` slot, so nothing was relying on\n // the baked-in origin. The URL stays the fallback for a free-tier asset,\n // which is minted no `cdnPath` and so has no reference to name.\n const src = formatMediaRef(media.mediaScope, media.mediaId) ?? media.url\n // The alt was a hardcoded '' (AGL-1896). Same reasoning as the listing\n // detail editor: no alt prompt exists on this surface, and a\n // markdown-lite image row's alt is fixed at insert time — so the asset's\n // own alt is the only description that could ever land here, and '' was\n // otherwise permanent.\n if (src)\n readmeEditorRef.current?.insertImage(\n inheritedMediaAlt({ assetAlt: media.alt }) ?? '',\n src,\n )\n }, [pickMedia])\n // What an untouched form looks like: empty for a first publish, the\n // listing's own content for an update (AGL-1008).\n const baseline = seedDraft(EMPTY_DRAFT, listing)\n const [draft, setDraft] = useState<PublishDraft>(() =>\n seedDraft(readDraft(orgId, listing?.$id), listing),\n )\n const [draftRestored, setDraftRestored] = useState(() =>\n draftDiffersFrom(\n seedDraft(readDraft(orgId, listing?.$id), listing),\n seedDraft(EMPTY_DRAFT, listing),\n ),\n )\n\n // Server-side problems, held against the field that caused them (AGL-1078)\n // instead of thrown at a snackbar that is gone before it is read. Cleared\n // on every submit so a fixed problem stops being shown as one.\n //\n // Objects, not strings (AGL-1091): the verifier has always answered with\n // `{level, message, check}` and this held `string[]`, so rendering a\n // rejection threw \"objects are not valid as a React child\" and the error\n // boundary ate the very card that was supposed to explain the rejection.\n // Normalized on arrival so a plain string from anywhere else still reads.\n const [problems, setProblems] = useState<PublishProblem[]>([])\n const [missingAttestations, setMissingAttestations] = useState<string[]>([])\n const [agreementProblem, setAgreementProblem] = useState('')\n // The publisher agreement (AGL-3407), asked for HERE rather than on the\n // Publisher Profile tab: offered as the form opens when the org's\n // acceptance is missing or stale, and presented again if the publish is\n // refused for it — accepting sends the same bundle and fields again.\n const agreement = usePublisherAgreementGate({ orgId, offer: true })\n const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({})\n\n const set = <K extends keyof PublishDraft>(key: K) =>\n (value: PublishDraft[K]) =>\n setDraft((current) => ({ ...current, [key]: value }))\n\n // Written back on every change — one small JSON blob, and the only thing\n // that makes a reload safe. Safe to run on the first pass now that the\n // restore happens during initialization: the value it writes IS the\n // restored one, so there is nothing left to clobber.\n useEffect(() => {\n if (!orgId) return\n try {\n window.localStorage.setItem(\n draftKey(orgId, listing?.$id),\n JSON.stringify(draft),\n )\n } catch {\n // Storage full or blocked — the form still works, it just won't survive.\n }\n }, [orgId, listing?.$id, draft])\n\n const clearDraft = useCallback(() => {\n try {\n window.localStorage.removeItem(draftKey(orgId, listing?.$id))\n } catch {\n // Nothing to do; the next publish overwrites it anyway.\n }\n }, [orgId, listing?.$id])\n\n const toggleAttestation = (id: string) =>\n setDraft((current) => ({\n ...current,\n attested: current.attested.includes(id)\n ? current.attested.filter((entry) => entry !== id)\n : [...current.attested, id],\n }))\n\n /**\n * What this page blocks on locally.\n *\n * On a first publish the changelog item is `updateOnly` and this form\n * genuinely cannot know whether the manifest id already has a listing —\n * the server answers that and names it in a 428. Demanding a changelog\n * attestation from a first-time publisher would be the worse failure: an\n * item that does not apply teaches people to tick without reading.\n *\n * Bound to a listing (AGL-1008) we DO know, so the update-only item is\n * asked here rather than arriving as a refusal after the upload.\n */\n const unattested = requiredAttestationIds(isUpdate).filter(\n (id) => !draft.attested.includes(id),\n )\n const unfilledSubjects = missingAttestationSubjects(\n { repositoryUrl: draft.repositoryUrl },\n isUpdate,\n )\n const repositoryInvalid =\n Boolean(draft.repositoryUrl.trim()) && !isHttpsUrl(draft.repositoryUrl)\n\n /**\n * The manifest id typed or pasted so far, if it parses.\n *\n * Only used to catch the one way a pre-bound update silently isn't one:\n * the server decides update-vs-new from `profileId` + the manifest id, so\n * a bundle whose id does not match this listing creates a SECOND listing\n * while the page says \"new version\". Cheap to notice here; impossible to\n * undo afterwards, because a published version is immutable.\n */\n const typedManifestId = (() => {\n const raw = draft.manifestText.trim()\n if (!raw) return ''\n try {\n const parsed = JSON.parse(raw) as { id?: unknown }\n return typeof parsed?.id === 'string' ? parsed.id : ''\n } catch {\n return ''\n }\n })()\n const manifestIdMismatch = Boolean(\n isUpdate && typedManifestId && listing?.pluginId &&\n typedManifestId !== listing.pluginId,\n )\n\n /**\n * What is serving customers right now (AGL-2368).\n *\n * This prints as \"v{X} is what installs today\", which is an INSTALL claim,\n * and it was reading a REVIEW verdict — the kill switch does not clear\n * `latestApprovedVersion`, so a publisher whose live version had been\n * stopped was told it was still installing, on the page they had come to\n * to ship its replacement.\n *\n * Falls through to nothing rather than to `latestVersion` when the offer is\n * revoked: the alert's other branch already says \"nothing installs until a\n * reviewer approves it\", which is the truth in that state.\n */\n const liveVersion = String(\n offeredPluginVersion(listing, revocation) ?? listing?.latestVersion ?? '',\n )\n\n const readManifest = async (): Promise<Record<string, unknown> | null> => {\n // A pasted manifest wins; otherwise read the chosen file.\n const raw = draft.manifestText.trim()\n ? draft.manifestText\n : manifestFile\n ? await manifestFile.text()\n : ''\n if (!raw) return null\n try {\n const parsed = JSON.parse(raw)\n return parsed && typeof parsed === 'object' ? parsed : null\n } catch {\n return null\n }\n }\n\n const submit = async () => {\n setProblems([])\n setMissingAttestations([])\n setAgreementProblem('')\n setFieldErrors({})\n if (!bundleFile) {\n setFieldErrors({ bundle: 'Choose a plugin bundle (.js) to upload.' })\n return\n }\n const manifest = await readManifest()\n if (!manifest) {\n setFieldErrors({\n manifest: 'Add a valid manifest (JSON) — id, name, version and entry.',\n })\n return\n }\n setBusy(true)\n try {\n const bundle = await fileToBase64(bundleFile)\n // Serialized once: a retry after the agreement is accepted sends the\n // bytes this attempt did, not whatever the form holds by then.\n const body = JSON.stringify({\n orgId,\n bundle,\n manifest,\n displayName:\n draft.displayName.trim() ||\n String((manifest as { name?: unknown }).name ?? '').trim(),\n description: draft.description.trim(),\n category: draft.category || undefined,\n changelog: draft.changelog.trim(),\n // A private plugin has no buyers — its only audience already owns\n // it — so it publishes free regardless of what the field held\n // before the publisher switched visibility.\n priceUsd:\n draft.visibility === 'private'\n ? 0\n : Math.max(0, Math.round(Number(draft.priceUsd) || 0)),\n visibility: draft.visibility,\n attestation: draft.attested,\n ...(draft.readme.trim() ? { readme: draft.readme.trim() } : {}),\n ...(draft.license.trim() ? { license: draft.license.trim() } : {}),\n ...(draft.repositoryUrl.trim()\n ? { repositoryUrl: draft.repositoryUrl.trim() }\n : {}),\n })\n const { response, payload, declined } = await agreement.send(() =>\n authorizedFetch(user, '/api/marketplace/publish-plugin', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n }),\n )\n if (!response.ok) {\n if (Array.isArray(payload?.problems)) {\n setProblems(\n payload.problems.map((problem: unknown) =>\n typeof problem === 'string'\n ? { message: problem }\n : {\n level: String(\n (problem as PublishProblem)?.level ?? 'error',\n ),\n message: String((problem as PublishProblem)?.message ?? ''),\n check: (problem as PublishProblem)?.check\n ? String((problem as PublishProblem).check)\n : undefined,\n },\n ),\n )\n }\n if (Array.isArray(payload?.missingAttestations)) {\n setMissingAttestations(payload.missingAttestations)\n }\n // The agreement was presented and closed without accepting\n // (AGL-3407). Held as an alert with the way back to it, not a toast:\n // the dialog already said why, and the form keeps everything.\n if (declined) {\n return void setAgreementProblem(String(payload.error ?? ''))\n }\n // A rejected subject names its field (AGL-1076), so put the message\n // where the value is rather than in a banner about a form.\n if (Array.isArray(payload?.missingAttestationSubjects)) {\n setFieldErrors(\n Object.fromEntries(\n payload.missingAttestationSubjects.map((field: string) => [\n field,\n String(payload.error ?? 'Required'),\n ]),\n ),\n )\n }\n return void enqueueSnackbar(payload?.error ?? 'Publish failed', {\n variant: response.status === 501 ? 'info' : 'error',\n allowDuplicate: true,\n })\n }\n // Somewhere to go (AGL-1078). The dialog closed onto the panel it\n // opened from, which said nothing about what had just happened; the\n // listing shows the version now queued for review.\n clearDraft()\n enqueueSnackbar(\n `Published v${payload?.version ?? '1'} — it is queued for review`,\n { variant: 'success' },\n )\n router.push(listingPath(basePath, String(payload?.listingId ?? '')))\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }\n\n // A price under the floor is refused by the publish route (AGL-2343), so the\n // button holds rather than letting a publisher upload a bundle and read the\n // minimum off a 400. A private plugin has no price at all — its field is\n // disabled and sends 0 — so it can never be blocked by this.\n const priceBelowFloor =\n draft.visibility !== 'private' &&\n isBelowMarketplacePriceFloor(draft.priceUsd)\n\n const blocked =\n busy ||\n !bundleFile ||\n unattested.length > 0 ||\n unfilledSubjects.length > 0 ||\n repositoryInvalid ||\n manifestIdMismatch ||\n priceBelowFloor\n\n return (\n <Stack spacing={2}>\n {isUpdate ? (\n /* AGL-1008. The mechanism was always right — same profileId plus\n manifest id bumps the listing, the new version enters review as\n pending, and the approved one keeps installing (AGL-966). The UI\n never told that story, so updating read like creating a second\n listing. */\n <Alert severity=\"info\">\n <Typography variant=\"subtitle2\">\n {`New version of ${listing?.displayName ?? 'your plugin'}`}\n </Typography>\n <Typography variant=\"caption\" component=\"div\">\n {liveVersion\n ? `v${liveVersion} is what installs today. It keeps installing ` +\n 'until a reviewer approves this one — nobody is upgraded ' +\n 'onto unreviewed code, and nothing you publish here can ' +\n 'change a version already installed.'\n : 'This version enters review. Nothing installs until a ' +\n 'reviewer approves it.'}\n </Typography>\n </Alert>\n ) : (\n <Alert severity=\"info\">\n {'Plugins publish sandboxed — they run isolated and can’t touch ' +\n 'site data directly. A reviewer verifies and signs yours before ' +\n 'it can run trusted.'}\n </Alert>\n )}\n\n {manifestIdMismatch ? (\n <Alert severity=\"warning\">\n {`This manifest says \"${typedManifestId}\", but ${\n listing?.displayName ?? 'this listing'\n } publishes \"${listing?.pluginId}\". Publishing it would create a ` +\n 'separate new listing rather than a new version of this one.'}\n </Alert>\n ) : null}\n\n {draftRestored ? (\n <Alert severity=\"info\" onClose={() => setDraftRestored(false)}>\n {'Picked up where you left off. Your bundle and manifest file are ' +\n 'not saved — choose them again before publishing.'}\n </Alert>\n ) : null}\n\n {agreementProblem ? (\n <Alert\n severity=\"warning\"\n action={\n <Button color=\"inherit\" size=\"small\" onClick={agreement.review}>\n {'Review the agreement'}\n </Button>\n }\n >\n {agreementProblem}\n </Alert>\n ) : null}\n {agreement.dialog}\n\n <CardDisplay\n header={isUpdate ? 'The new bundle and manifest' : 'Bundle and manifest'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#publishing-a-version',\n excerpt:\n 'One self-contained bundle plus its manifest — verified before ' +\n 'it is stored, and content-addressed once it is.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <Stack spacing={0.5}>\n <Typography variant=\"subtitle2\">{'Bundle (.js)'}</Typography>\n <input\n ref={bundleRef}\n type=\"file\"\n accept=\".js,text/javascript,application/javascript\"\n hidden\n onChange={(event) =>\n setBundleFile(event.target.files?.[0] ?? null)\n }\n />\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button size=\"small\" onClick={() => bundleRef.current?.click()}>\n {'Choose bundle'}\n </Button>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {bundleFile?.name ?? 'No file chosen'}\n </Typography>\n </Stack>\n <Typography\n variant=\"caption\"\n color={fieldErrors['bundle'] ? 'error.main' : 'text.secondary'}\n >\n {fieldErrors['bundle'] ??\n 'One self-contained bundle. It’s parsed and checked before ' +\n 'publishing — forbidden APIs, size, and every network ' +\n 'call against the origins your manifest declares.'}\n </Typography>\n </Stack>\n\n <Stack spacing={0.5}>\n <Typography variant=\"subtitle2\">\n {'Manifest (JSON: id, name, version, entry)'}\n </Typography>\n <input\n ref={manifestRef}\n type=\"file\"\n accept=\".json,application/json\"\n hidden\n onChange={(event) =>\n setManifestFile(event.target.files?.[0] ?? null)\n }\n />\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button size=\"small\" onClick={() => manifestRef.current?.click()}>\n {'Choose manifest.json'}\n </Button>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {manifestFile?.name ?? 'or paste below'}\n </Typography>\n </Stack>\n <TextField\n placeholder='{ \"id\": \"acme-widget\", \"name\": \"Widget\", \"version\": \"1.0.0\", \"entry\": \"index.js\" }'\n value={draft.manifestText}\n onChange={(event) => set('manifestText')(event.target.value)}\n size=\"small\"\n multiline\n minRows={4}\n fullWidth\n error={Boolean(fieldErrors['manifest'])}\n helperText={fieldErrors['manifest'] ?? ' '}\n />\n </Stack>\n\n {problems.length ? (\n <Alert\n severity={\n problems.some((problem) => problem.level !== 'warning')\n ? 'error'\n : 'warning'\n }\n >\n <Typography variant=\"subtitle2\">\n {problems.some((problem) => problem.level !== 'warning')\n ? 'Bundle failed verification'\n : 'Bundle verified, with things to check'}\n </Typography>\n <ul style={{ margin: '4px 0 0', paddingLeft: 18 }}>\n {problems.map((problem, index) => (\n <li key={`${problem.check ?? 'problem'}-${index}`}>\n <Typography variant=\"caption\">\n {problem.check ? `${problem.check}: ` : ''}\n {problem.message}\n </Typography>\n </li>\n ))}\n </ul>\n </Alert>\n ) : null}\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header={'Listing'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#authoring-your-listing',\n excerpt:\n 'What a reviewer reads first and a buyer reads before running ' +\n 'third-party code.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <TextField\n label=\"Listing name\"\n helperText=\"Defaults to the manifest name\"\n value={draft.displayName}\n onChange={(event) => set('displayName')(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"Description\"\n helperText=\"The one-line summary on browse cards\"\n value={draft.description}\n onChange={(event) => set('description')(event.target.value)}\n size=\"small\"\n multiline\n minRows={2}\n />\n <TextField\n select\n label=\"Category\"\n value={draft.category}\n onChange={(event) => set('category')(event.target.value)}\n size=\"small\"\n >\n <MenuItem value=\"\">{'None'}</MenuItem>\n {LISTING_CATEGORIES.map((entry) => (\n <MenuItem key={entry} value={entry}>\n {entry}\n </MenuItem>\n ))}\n </TextField>\n {/* The same editor the listing detail page uses (AGL-1080). The\n first time a publisher writes the document reviewers read\n first used to get the worst tool we have, and the second time\n the good one — for the same field. The AGL-969 attestation\n made that worse by asking them to confirm the README\n documents what data the plugin handles, in a box too small to\n see whether it does. */}\n <MarkdownField\n label=\"README\"\n value={draft.readme}\n onChange={set('readme')}\n onPickImageFromMedia={insertReadmeImage}\n editorRef={(handle) => {\n readmeEditorRef.current = handle\n }}\n helperText={\n 'Shown on your listing page — what it does, how to configure ' +\n 'it, and what it reads, stores or sends. Reviewers and ' +\n 'cautious buyers read this first.'\n }\n />\n {/* The only field that exclusively concerns updates (AGL-1080).\n It was a single line labelled `Changelog` and nothing else,\n presented as an equal peer of Category — while AGL-969 attests\n to it and AGL-976 builds the listing's changelog tab out of\n it. The helper names both audiences, because \"what changed\"\n means something different to each. */}\n <TextField\n label=\"Changelog\"\n placeholder=\"Fixed the timer drift on Safari; added a compact layout\"\n helperText={\n isUpdate\n ? 'The field that matters most on an update. Two audiences: ' +\n 'the reviewer, comparing these bytes against ' +\n (liveVersion ? `v${liveVersion}` : 'the last approved ' +\n 'version') +\n ', and every installer deciding whether to move off the ' +\n 'version they are running.'\n : 'Two audiences: the reviewer, comparing this version ' +\n 'against the last approved one, and every installer who ' +\n 'reads it on your listing’s changelog tab before ' +\n 'updating. On a first version there is nothing to compare ' +\n 'against — say what the plugin does instead, or leave it.'\n }\n value={draft.changelog}\n onChange={(event) => set('changelog')(event.target.value)}\n size=\"small\"\n multiline\n minRows={3}\n />\n {/* AGL-1076: the subject of the repository attestation below. */}\n <TextField\n label=\"Repository URL\"\n placeholder=\"https://github.com/acme/widget\"\n required\n error={repositoryInvalid || Boolean(fieldErrors['repositoryUrl'])}\n helperText={\n repositoryInvalid\n ? 'Must be an https URL.'\n : (fieldErrors['repositoryUrl'] ??\n 'The source for this bundle. A reviewer opens it first — ' +\n 'it is what the repository confirmation below is about.')\n }\n value={draft.repositoryUrl}\n onChange={(event) => set('repositoryUrl')(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"License\"\n placeholder=\"MIT\"\n helperText=\"Short label, e.g. MIT or Apache-2.0\"\n value={draft.license}\n onChange={(event) => set('license')(event.target.value)}\n size=\"small\"\n />\n </Stack>\n </CardDisplay>\n\n <CardDisplay\n header={'Who can install it, and for how much'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#private-plugins',\n excerpt:\n 'Private is a choice about audience, not about trust — it takes ' +\n 'the identical review path.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {/* Private plugins (AGL-968/992): deliberately worded as an\n AUDIENCE choice — private is not a faster lane, and the caption\n says so, because \"skip the queue\" is the reading it would\n otherwise invite. */}\n <TextField\n select\n label=\"Who can install this\"\n value={draft.visibility}\n // Set on FIRST publish only — the server ignores it on a version\n // bump (AGL-968), so offering the choice here would be a control\n // that silently does nothing. Change it from the listing.\n disabled={isUpdate}\n onChange={(event) =>\n set('visibility')(event.target.value as 'public' | 'private')\n }\n size=\"small\"\n helperText={\n isUpdate\n ? 'Set when the listing was created. Change it from the ' +\n 'listing — a new version never changes who can install it.'\n :\n draft.visibility === 'private'\n ? 'Private plugins take the same review path — same ' +\n 'queue, same checklist, same verifier, same signature ' +\n 'for realm trust. They are never listed in the ' +\n 'marketplace, and only your sites can install them.'\n : 'Listed in the marketplace for every workspace once a ' +\n 'reviewer approves it.'\n }\n >\n <MenuItem value=\"public\">\n {'Anyone — publish to the marketplace'}\n </MenuItem>\n <MenuItem value=\"private\">\n {'Only this organization — private plugin'}\n </MenuItem>\n </TextField>\n <TextField\n label=\"Price (USD)\"\n // A private plugin has no buyers, and a price on one would only\n // send the publisher through Stripe onboarding to sell to\n // themselves.\n disabled={draft.visibility === 'private'}\n // The minimum price (AGL-2343), from the same functions every other\n // publish form reads, so no two forms can quote different figures\n // at a publisher — and stated up front rather than only on refusal.\n error={priceBelowFloor}\n helperText={\n draft.visibility === 'private'\n ? 'Private plugins are free — nobody else can install them.'\n : (marketplacePriceCostNote(draft.priceUsd) ??\n marketplacePriceFloorHint(\n 'Paid listings need payouts set up.',\n ))\n }\n type=\"number\"\n value={draft.visibility === 'private' ? '0' : draft.priceUsd}\n onChange={(event) => set('priceUsd')(event.target.value)}\n size=\"small\"\n />\n </Stack>\n </CardDisplay>\n\n {/* The checklist last, in full view of the publish button (AGL-969 /\n AGL-1078). In the dialog it sat below the button and had to be\n scrolled past to be seen at all. Every item is a statement only the\n publisher can make. */}\n <CardDisplay\n header={'Before you publish'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#before-you-publish',\n excerpt:\n 'Recorded against this exact bundle, with your name and the ' +\n 'date, and shown to the reviewer.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Recorded against this exact bundle, with your name and the ' +\n 'date, and shown to the reviewer. Republishing the same ' +\n 'version number asks again — the bytes changed.'}\n </Typography>\n {missingAttestations.length ? (\n <Alert severity=\"warning\">\n {'This plugin already has a published version, so the ' +\n 'highlighted item applies too.'}\n </Alert>\n ) : null}\n {PUBLISHER_ATTESTATION.map((item) => {\n const flagged = missingAttestations.includes(item.id)\n return (\n <Stack key={item.id} spacing={0.25}>\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n checked={draft.attested.includes(item.id)}\n disabled={busy}\n onChange={() => toggleAttestation(item.id)}\n />\n }\n label={\n <Stack\n useFlexGap\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap' }}\n >\n <Typography\n variant=\"body2\"\n color={flagged ? 'warning.main' : undefined}\n >\n {item.label}\n </Typography>\n {item.updateOnly ? (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Updates only\"\n />\n ) : null}\n </Stack>\n }\n />\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ pl: 4 }}\n >\n {item.detail}\n </Typography>\n </Stack>\n )\n })}\n </Stack>\n </CardDisplay>\n\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => void submit()}\n disabled={blocked}\n >\n {busy\n ? 'Publishing…'\n : !bundleFile\n ? 'Choose a bundle'\n : unattested.length\n ? `Confirm ${unattested.length} more`\n : unfilledSubjects.length || repositoryInvalid\n ? 'Add a repository URL'\n : isUpdate\n ? 'Publish new version'\n : draft.visibility === 'private'\n ? 'Publish privately'\n : 'Publish plugin'}\n </Button>\n <Button\n disabled={busy}\n onClick={() => {\n clearDraft()\n setDraft(baseline)\n setBundleFile(null)\n setManifestFile(null)\n setDraftRestored(false)\n }}\n >\n {'Discard draft'}\n </Button>\n </Stack>\n\n </Stack>\n )\n}\n\nPublishPluginForm.displayName = 'PublishPluginForm'\n\nexport default PublishPluginForm\n"],"names":["formatMediaRef","offeredPluginVersion","useMediaPicker","isBelowMarketplacePriceFloor","marketplacePriceCostNote","marketplacePriceFloorHint","CardDisplay","useSnackbar","Alert","Button","Checkbox","Chip","FormControlLabel","MenuItem","Stack","TextField","Typography","useRouter","useCallback","useEffect","useRef","useState","useUser","missingAttestationSubjects","PUBLISHER_ATTESTATION","requiredAttestationIds","MarkdownField","pluginDocsHelp","inheritedMediaAlt","authorizedFetch","listingPath","usePublisherAgreementGate","LISTING_CATEGORIES","isHttpsUrl","value","test","trim","length","fileToBase64","file","buffer","arrayBuffer","binary","bytes","Uint8Array","i","String","fromCharCode","btoa","EMPTY_DRAFT","manifestText","displayName","description","category","changelog","priceUsd","readme","license","repositoryUrl","visibility","attested","draftKey","orgId","listingId","readDraft","window","stored","localStorage","getItem","JSON","parse","seedDraft","draft","listing","$id","seeded","carry","key","categories","draftDiffersFrom","baseline","Object","keys","some","undefined","Array","isArray","other","entry","index","PublishPluginForm","props","fieldErrors","basePath","revocation","isUpdate","Boolean","data","user","router","enqueueSnackbar","busy","setBusy","bundleRef","manifestRef","bundleFile","setBundleFile","manifestFile","setManifestFile","readmeEditorRef","pickMedia","insertReadmeImage","media","kind","src","mediaScope","mediaId","url","current","insertImage","assetAlt","alt","setDraft","draftRestored","setDraftRestored","problems","setProblems","missingAttestations","setMissingAttestations","agreementProblem","setAgreementProblem","agreement","offer","setFieldErrors","set","setItem","stringify","clearDraft","removeItem","toggleAttestation","id","includes","filter","unattested","unfilledSubjects","repositoryInvalid","typedManifestId","raw","parsed","manifestIdMismatch","pluginId","liveVersion","latestVersion","readManifest","text","submit","bundle","manifest","body","name","Math","max","round","Number","attestation","response","payload","declined","send","method","headers","ok","map","problem","message","level","check","error","fromEntries","field","variant","status","allowDuplicate","version","push","console","priceBelowFloor","blocked","spacing","severity","component","onClose","action","color","size","onClick","review","dialog","header","help","anchor","excerpt","contentGutterX","contentGutterY","input","ref","type","accept","hidden","onChange","event","target","files","direction","sx","alignItems","click","noWrap","placeholder","multiline","minRows","fullWidth","helperText","ul","style","margin","paddingLeft","li","label","select","onPickImageFromMedia","editorRef","handle","required","disabled","item","flagged","control","checked","useFlexGap","flexWrap","updateOnly","pl","detail"],"mappings":"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"}
@@ -183,6 +183,7 @@ const PLACEMENT_NOUNS = {
183
183
  children: `${site.affectedScreens} published page` + `${site.affectedScreens === 1 ? '' : 's'} affected`
184
184
  }),
185
185
  /*#__PURE__*/ _jsxs(Stack, {
186
+ useFlexGap: true,
186
187
  direction: "row",
187
188
  spacing: 1,
188
189
  sx: {