@anthusai/papyrus 5.43.0-next.4 → 5.43.0-next.41

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 (118) hide show
  1. package/amplify/data/resource.js +6 -0
  2. package/amplify/data/resource.ts +7 -0
  3. package/amplify/data/schema.js +6 -0
  4. package/amplify/data/schema.ts +7 -0
  5. package/amplify/functions/category-action/handler.ts +16 -8
  6. package/amplify/functions/content-actions/handler.py +8 -0
  7. package/amplify/functions/content-actions/requirements.txt +2 -0
  8. package/amplify/functions/content-actions/resource.js +1 -1
  9. package/amplify/functions/content-actions/resource.ts +1 -1
  10. package/amplify/functions/model-attachment-upload/handler.ts +1 -0
  11. package/amplify/functions/monitoring-view/schema.js +16 -0
  12. package/amplify/functions/monitoring-view/schema.ts +16 -0
  13. package/amplify/functions/procedure-action/handler.ts +2 -10
  14. package/amplify/functions/proposal-actions/proposals.py +20 -3
  15. package/amplify/plugins/reader-steering/function/handler.py +1 -3
  16. package/amplify/plugins/reader-steering/function/moderation.py +19 -0
  17. package/app/api/newsroom/source-frameable/route.ts +12 -0
  18. package/app/api/newsroom/source-icon/route.ts +20 -0
  19. package/app/newsroom/[section]/[...selection]/page.tsx +2 -0
  20. package/app/newsroom/[section]/page.tsx +1 -0
  21. package/bin/papyrus-app.mjs +12 -1
  22. package/bin/papyrus-infra.mjs +21 -1
  23. package/components/auto-accepted-badge.tsx +21 -0
  24. package/components/conversation-context.tsx +52 -0
  25. package/components/conversation-provider.tsx +20 -0
  26. package/components/conversation-thread.tsx +174 -0
  27. package/components/decision-control.tsx +306 -0
  28. package/components/dev-sandbox-editor-sign-in.tsx +2 -2
  29. package/components/markdown-context.tsx +412 -0
  30. package/components/monitoring-overview-view.tsx +143 -21
  31. package/components/monitoring-panel.tsx +64 -4
  32. package/components/needs-me-bodies.tsx +302 -0
  33. package/components/needs-me-detail.tsx +24 -0
  34. package/components/needs-me-feed.tsx +594 -0
  35. package/components/needs-me-reference-detail.tsx +79 -0
  36. package/components/needs-me-shared.tsx +48 -0
  37. package/components/news-desk-client-provider.tsx +24 -3
  38. package/components/news-desk-page.tsx +2 -1
  39. package/components/news-desk-taxonomy-client.ts +253 -31
  40. package/components/newsroom-access-gate.tsx +13 -20
  41. package/components/newsroom-board-skeleton.tsx +20 -0
  42. package/components/newsroom-board-view.tsx +2 -6
  43. package/components/newsroom-client-shell.tsx +2 -1
  44. package/components/newsroom-ops-overview.tsx +88 -73
  45. package/components/newsroom-ops-shell.tsx +8 -28
  46. package/components/newsroom-organizer.css +127 -3
  47. package/components/newsroom-references-view.tsx +334 -158
  48. package/components/notification-cards.tsx +370 -0
  49. package/components/notification-center.tsx +376 -213
  50. package/components/papyrus-console-shell.tsx +2 -1
  51. package/components/proposals-panel.tsx +21 -24
  52. package/components/proposals-view.tsx +4 -2
  53. package/components/reader-auth-control.tsx +3 -1
  54. package/components/reference-capture-client.ts +138 -0
  55. package/components/reference-capture-panel.tsx +268 -0
  56. package/components/reference-conversation.tsx +43 -0
  57. package/components/reference-feed.tsx +514 -0
  58. package/components/reference-review-card.tsx +62 -197
  59. package/components/reference-source-preview.tsx +27 -5
  60. package/components/reference-stories.tsx +34 -0
  61. package/components/references-page-loading.tsx +61 -0
  62. package/components/references-prefetch.ts +52 -0
  63. package/components/story-reporting-trail-client.ts +45 -8
  64. package/components/story-reporting-trail.tsx +24 -13
  65. package/components/topic-steering-workspace.tsx +50 -439
  66. package/components/ui/auto-grow-textarea.tsx +18 -0
  67. package/components/use-conversation.ts +84 -0
  68. package/components/use-media-query.ts +16 -0
  69. package/components/use-reference-preview-attachments.ts +101 -0
  70. package/components/use-reference-ratings.ts +189 -0
  71. package/infra/amplify-app-shell.js +18 -2
  72. package/infra/amplify-app-shell.ts +18 -2
  73. package/infra/chat-stack.js +222 -0
  74. package/infra/chat-stack.ts +250 -0
  75. package/infra/chat.test.js +142 -0
  76. package/infra/chat.test.ts +151 -0
  77. package/infra/index.js +1 -0
  78. package/infra/site-config.js +58 -1
  79. package/infra/site-config.ts +78 -1
  80. package/lib/category-repository.ts +6 -1
  81. package/lib/content-actions-client.ts +20 -0
  82. package/lib/conversation.ts +154 -0
  83. package/lib/local-preview-feed-fixture.ts +63 -0
  84. package/lib/local-preview-seed.ts +24 -2
  85. package/lib/local-preview-synthetic-rejects.ts +41 -0
  86. package/lib/monitoring-client.ts +29 -2
  87. package/lib/monitoring-overview.ts +52 -1
  88. package/lib/monitoring-paging.ts +58 -0
  89. package/lib/needs-me-items.ts +289 -0
  90. package/lib/needs-me-ranking.ts +315 -0
  91. package/lib/newsroom-all-pages.ts +21 -0
  92. package/lib/newsroom-chat-identity.ts +2 -1
  93. package/lib/newsroom-index-filters.ts +18 -0
  94. package/lib/newsroom-nav.ts +1 -1
  95. package/lib/newsroom-organizer-nav.ts +2 -1
  96. package/lib/newsroom-references.ts +25 -1
  97. package/lib/notification-feed.ts +212 -0
  98. package/lib/proposals-client.ts +29 -0
  99. package/lib/reader-subject.ts +3 -2
  100. package/lib/reference-capture.ts +294 -0
  101. package/lib/reference-feed-cache.ts +170 -0
  102. package/lib/reference-feed-ranking.ts +236 -0
  103. package/lib/reference-policy.ts +90 -0
  104. package/lib/reference-preview.ts +112 -0
  105. package/lib/relevance-decisions.ts +6 -2
  106. package/lib/review-client.ts +71 -5
  107. package/lib/review-drafts.ts +277 -0
  108. package/lib/review-fixture.ts +56 -2
  109. package/lib/review-requests.ts +89 -24
  110. package/lib/site-brand.ts +2 -0
  111. package/lib/source-frameable.ts +77 -0
  112. package/lib/source-icon.ts +104 -0
  113. package/lib/staff-groups.ts +23 -0
  114. package/lib/staging-gate.ts +2 -2
  115. package/lib/story-reporting-trail.ts +33 -2
  116. package/package.json +45 -2
  117. package/routes.manifest.json +23 -1
  118. package/components/newsroom-overview-skeleton.tsx +0 -25
@@ -0,0 +1,104 @@
1
+ import { fetchPublic } from "./source-frameable";
2
+
3
+ /**
4
+ * A source's own icon, fetched on the server. Guessing `/favicon.ico` from the browser fails often: some sites serve a fully
5
+ * transparent placeholder there, and others refuse requests from another site. The page's own `<link rel="icon">` tags name
6
+ * the icon the site actually uses, so the newsroom reads those first and passes the image through.
7
+ */
8
+
9
+ const MAX_HTML_BYTES = 256 * 1024;
10
+ const MAX_ICON_BYTES = 256 * 1024;
11
+ /** A bare 16x16 ICO is about 200 bytes; at that size it is often an empty placeholder, so the guessed path must beat it. */
12
+ const MIN_GUESSED_ICON_BYTES = 300;
13
+
14
+ export type SourceIcon = { body: ArrayBuffer; contentType: string };
15
+
16
+ /** A bare host name such as `www.brookings.edu`: letters, digits, hyphens and dots only. */
17
+ export function isHostName(host: string): boolean {
18
+ return host.length <= 253 && /^(?=.*[a-z])[a-z0-9-]+(\.[a-z0-9-]+)+$/i.test(host);
19
+ }
20
+
21
+ function attribute(tag: string, name: string): string | null {
22
+ const match = tag.match(new RegExp(`\\s${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, "i"));
23
+ return match ? (match[1] ?? match[2] ?? match[3] ?? "") : null;
24
+ }
25
+
26
+ /** The icons a page declares, best first: touch icons, then the largest declared size. Mask icons are single-colour stencils and are skipped. */
27
+ export function iconCandidates(html: string, base: string): string[] {
28
+ const found: { href: string; score: number }[] = [];
29
+ for (const tag of html.match(/<link\b[^>]*>/gi) ?? []) {
30
+ const rel = (attribute(tag, "rel") ?? "").toLowerCase().split(/\s+/);
31
+ if (!rel.some((word) => word === "icon" || word === "apple-touch-icon" || word === "apple-touch-icon-precomposed")) continue;
32
+ const href = attribute(tag, "href");
33
+ if (!href) continue;
34
+ let absolute: string;
35
+ try { absolute = new URL(href, base).toString(); } catch { continue; }
36
+ const size = Math.max(0, ...(attribute(tag, "sizes") ?? "").split(/\s+/).map((s) => Number.parseInt(s, 10)).filter(Number.isFinite));
37
+ const touch = rel.some((word) => word.startsWith("apple-touch-icon"));
38
+ found.push({ href: absolute, score: (touch ? 10_000 : 0) + (size || (touch ? 180 : 16)) });
39
+ }
40
+ return [...new Set(found.sort((a, b) => b.score - a.score).map(({ href }) => href))];
41
+ }
42
+
43
+ async function readLimited(response: Response, limit: number): Promise<ArrayBuffer | null> {
44
+ const declared = Number(response.headers.get("content-length"));
45
+ if (declared > limit) { void response.body?.cancel(); return null; }
46
+ const body = await response.arrayBuffer().catch(() => null);
47
+ return body && body.byteLength <= limit ? body : null;
48
+ }
49
+
50
+ /** The first `limit` bytes of a page: icons are declared in its head, and some home pages run to a megabyte. */
51
+ async function readPrefix(response: Response, limit: number): Promise<string> {
52
+ const reader = response.body?.getReader();
53
+ if (!reader) return "";
54
+ const chunks: Uint8Array[] = [];
55
+ let total = 0;
56
+ try {
57
+ while (total < limit) {
58
+ const { done, value } = await reader.read();
59
+ if (done) break;
60
+ chunks.push(value);
61
+ total += value.byteLength;
62
+ }
63
+ } catch {
64
+ // keep what arrived
65
+ } finally {
66
+ void reader.cancel().catch(() => undefined);
67
+ }
68
+ const bytes = new Uint8Array(Math.min(total, limit));
69
+ let offset = 0;
70
+ for (const chunk of chunks) {
71
+ const part = chunk.subarray(0, bytes.length - offset);
72
+ bytes.set(part, offset);
73
+ offset += part.byteLength;
74
+ if (offset >= bytes.length) break;
75
+ }
76
+ return new TextDecoder().decode(bytes);
77
+ }
78
+
79
+ async function fetchIcon(url: string, minBytes: number): Promise<SourceIcon | null> {
80
+ const response = await fetchPublic(url, { accept: "image/*" });
81
+ if (!response) return null;
82
+ const contentType = (response.headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
83
+ if (!response.ok || !contentType.startsWith("image/")) { void response.body?.cancel(); return null; }
84
+ const body = await readLimited(response, MAX_ICON_BYTES);
85
+ return body && body.byteLength >= minBytes ? { body, contentType } : null;
86
+ }
87
+
88
+ /** The host's best declared icon, else its `/favicon.ico` when that is more than a placeholder, else null. */
89
+ export async function fetchSourceIcon(host: string): Promise<SourceIcon | null> {
90
+ if (!isHostName(host)) return null;
91
+ const home = `https://${host}/`;
92
+ const page = await fetchPublic(home, { accept: "text/html" });
93
+ let candidates: string[] = [];
94
+ if (page?.ok && (page.headers.get("content-type") ?? "").includes("html")) {
95
+ candidates = iconCandidates(await readPrefix(page, MAX_HTML_BYTES), page.url || home);
96
+ } else {
97
+ void page?.body?.cancel();
98
+ }
99
+ for (const candidate of candidates.slice(0, 4)) {
100
+ const icon = await fetchIcon(candidate, 1);
101
+ if (icon) return icon;
102
+ }
103
+ return fetchIcon(new URL("/favicon.ico", home).toString(), MIN_GUESSED_ICON_BYTES);
104
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Who counts as newsroom staff. `admin` has every editor right: a site owner who is in `admin` but not `editor` can do
3
+ * everything an editor can. Every editor check in the browser and in the Lambdas reads this one list.
4
+ */
5
+ export const STAFF_GROUPS = ["editor", "admin"] as const;
6
+
7
+ /** True when any group is `editor` or `admin`. */
8
+ export function hasEditorRights(groups: Iterable<unknown> | null | undefined): boolean {
9
+ if (!groups) return false;
10
+ for (const group of groups) {
11
+ if (typeof group === "string" && (STAFF_GROUPS as readonly string[]).includes(group.trim().toLowerCase())) return true;
12
+ }
13
+ return false;
14
+ }
15
+
16
+ /**
17
+ * Cognito groups from a `cognito:groups` claim, which arrives as an array, a JSON array, a bracketed list
18
+ * (`[admin Google_123]`), or a comma or space separated string depending on who forwarded it.
19
+ */
20
+ export function claimGroups(value: unknown): string[] {
21
+ const raw = Array.isArray(value) ? value.map((entry) => String(entry)) : typeof value === "string" ? value.split(/[\s,]+/) : [];
22
+ return raw.map((entry) => entry.trim().replace(/^["'[\](){}]+|["'[\](){}]+$/g, "")).filter(Boolean);
23
+ }
@@ -1,10 +1,10 @@
1
1
  import type { NextRequest, NextResponse } from "next/server";
2
2
  import { fetchAuthSession } from "aws-amplify/auth/server";
3
3
  import { getAmplifyServerRuntime } from "./amplify-server-runtime";
4
+ import { hasEditorRights } from "./staff-groups";
4
5
 
5
6
  export type StagingAccess = "anonymous" | "forbidden" | "ok";
6
7
 
7
- const STAGING_ALLOWED_GROUPS = ["editor", "admin"];
8
8
 
9
9
  export function groupsFromIdTokenPayload(payload: Record<string, unknown> | undefined): string[] {
10
10
  const raw = payload?.["cognito:groups"];
@@ -15,7 +15,7 @@ export function groupsFromIdTokenPayload(payload: Record<string, unknown> | unde
15
15
 
16
16
  export function accessForGroups(groups: string[] | null): StagingAccess {
17
17
  if (groups === null) return "anonymous";
18
- return groups.some((group) => STAGING_ALLOWED_GROUPS.includes(group)) ? "ok" : "forbidden";
18
+ return hasEditorRights(groups) ? "ok" : "forbidden";
19
19
  }
20
20
 
21
21
  export async function getStagingAccess(request: NextRequest, response: NextResponse): Promise<StagingAccess> {
@@ -63,8 +63,12 @@ export type TrailReference = {
63
63
  referenceLineageId: string | null;
64
64
  title: string | null;
65
65
  sourceUri: string | null;
66
- /** consulted: read during reporting; cited: a citation in the article. */
67
- role: "consulted" | "cited";
66
+ /** based_on: the story is made from this Reference; consulted: read during reporting; cited: a citation in the article. */
67
+ role: "based_on" | "consulted" | "cited";
68
+ /** The site that published the Reference (its preview's site name, else the host of its address). */
69
+ siteName: string | null;
70
+ /** The Reference's preview image address. It is shown from its own site, never copied. */
71
+ previewImageUrl: string | null;
68
72
  note: string | null;
69
73
  citationKey: string | null;
70
74
  addedBy: string | null;
@@ -104,3 +108,30 @@ export function storyMessageFeed(trail: StoryReportingTrail): StoryFeedEntry[] {
104
108
  const sequenceOf = (entry: StoryFeedEntry) => (entry.entryKind === "message" ? entry.sequenceNumber ?? 0 : 0);
105
109
  return [...messages, ...references].sort((left, right) => right.createdAt.localeCompare(left.createdAt) || sequenceOf(right) - sequenceOf(left));
106
110
  }
111
+
112
+ const ROLE_ORDER = { based_on: 0, cited: 1, consulted: 2 } as const;
113
+
114
+ /** The References of a story, the ones it is based on first. */
115
+ export function referencesByRole(references: readonly TrailReference[]): TrailReference[] {
116
+ return [...references].sort((left, right) => ROLE_ORDER[left.role] - ROLE_ORDER[right.role]);
117
+ }
118
+
119
+ export function referenceRoleLabel(role: TrailReference["role"]): string {
120
+ return role === "based_on" ? "Based on" : role === "cited" ? "Cited" : "Consulted";
121
+ }
122
+
123
+ /** A story that a Reference supports, as the Reference view lists it. */
124
+ export type ReferenceStory = {
125
+ relationId: string;
126
+ itemId: string;
127
+ lineageId: string;
128
+ title: string | null;
129
+ stage: string | null;
130
+ role: TrailReference["role"];
131
+ };
132
+
133
+ export function siteNameOf(sourceUri: string | null | undefined, preferred?: string | null): string | null {
134
+ if (preferred) return preferred;
135
+ if (!sourceUri) return null;
136
+ try { return new URL(sourceUri).hostname.replace(/^www\./, ""); } catch { return null; }
137
+ }
package/package.json CHANGED
@@ -75,22 +75,33 @@
75
75
  "./components/archive-grid": "./components/archive-grid.tsx",
76
76
  "./components/archive-shell": "./components/archive-shell.tsx",
77
77
  "./components/article-video": "./components/article-video.tsx",
78
+ "./components/auto-accepted-badge": "./components/auto-accepted-badge.tsx",
78
79
  "./components/automation-panel": "./components/automation-panel.tsx",
79
80
  "./components/automation-run-now": "./components/automation-run-now.tsx",
80
81
  "./components/automation-view": "./components/automation-view.tsx",
81
82
  "./components/blog-page-background": "./components/blog-page-background.tsx",
83
+ "./components/conversation-context": "./components/conversation-context.tsx",
84
+ "./components/conversation-provider": "./components/conversation-provider.tsx",
85
+ "./components/conversation-thread": "./components/conversation-thread.tsx",
82
86
  "./components/curation-delegation-client": "./components/curation-delegation-client.ts",
87
+ "./components/decision-control": "./components/decision-control.tsx",
83
88
  "./components/dev-sandbox-editor-sign-in": "./components/dev-sandbox-editor-sign-in.tsx",
84
89
  "./components/editorial-checks-admin-panel": "./components/editorial-checks-admin-panel.tsx",
85
90
  "./components/editorial-finding-card": "./components/editorial-finding-card.tsx",
86
91
  "./components/editorial-findings-panel": "./components/editorial-findings-panel.tsx",
87
92
  "./components/editorial-preview-popover": "./components/editorial-preview-popover.tsx",
88
93
  "./components/item-stream-view": "./components/item-stream-view.tsx",
94
+ "./components/markdown-context": "./components/markdown-context.tsx",
89
95
  "./components/markus-body-editor": "./components/markus-body-editor.tsx",
90
96
  "./components/markus-ir-preview": "./components/markus-ir-preview.tsx",
91
97
  "./components/moderation-panel": "./components/moderation-panel.tsx",
92
98
  "./components/monitoring-overview-view": "./components/monitoring-overview-view.tsx",
93
99
  "./components/monitoring-panel": "./components/monitoring-panel.tsx",
100
+ "./components/needs-me-bodies": "./components/needs-me-bodies.tsx",
101
+ "./components/needs-me-detail": "./components/needs-me-detail.tsx",
102
+ "./components/needs-me-feed": "./components/needs-me-feed.tsx",
103
+ "./components/needs-me-reference-detail": "./components/needs-me-reference-detail.tsx",
104
+ "./components/needs-me-shared": "./components/needs-me-shared.tsx",
94
105
  "./components/news-desk-client-provider": "./components/news-desk-client-provider.tsx",
95
106
  "./components/news-desk-page": "./components/news-desk-page.tsx",
96
107
  "./components/news-desk-taxonomy-client": "./components/news-desk-taxonomy-client.ts",
@@ -102,6 +113,7 @@
102
113
  "./components/newsroom-articles-view": "./components/newsroom-articles-view.tsx",
103
114
  "./components/newsroom-assignment-detail": "./components/newsroom-assignment-detail.tsx",
104
115
  "./components/newsroom-assignments-view": "./components/newsroom-assignments-view.tsx",
116
+ "./components/newsroom-board-skeleton": "./components/newsroom-board-skeleton.tsx",
105
117
  "./components/newsroom-board-view": "./components/newsroom-board-view.tsx",
106
118
  "./components/newsroom-client-shell": "./components/newsroom-client-shell.tsx",
107
119
  "./components/newsroom-curation-bootstrap": "./components/newsroom-curation-bootstrap.tsx",
@@ -109,7 +121,6 @@
109
121
  "./components/newsroom-mobile-navigation": "./components/newsroom-mobile-navigation.tsx",
110
122
  "./components/newsroom-ops-overview": "./components/newsroom-ops-overview.tsx",
111
123
  "./components/newsroom-ops-shell": "./components/newsroom-ops-shell.tsx",
112
- "./components/newsroom-overview-skeleton": "./components/newsroom-overview-skeleton.tsx",
113
124
  "./components/newsroom-references-view": "./components/newsroom-references-view.tsx",
114
125
  "./components/newsroom-theme-fonts/broadsheet-green": "./components/newsroom-theme-fonts/broadsheet-green.tsx",
115
126
  "./components/newsroom-theme-fonts/newspaper-gothic": "./components/newsroom-theme-fonts/newspaper-gothic.tsx",
@@ -117,6 +128,7 @@
117
128
  "./components/newsroom-theme-fonts/refined-newsprint": "./components/newsroom-theme-fonts/refined-newsprint.tsx",
118
129
  "./components/newsroom-theme": "./components/newsroom-theme.tsx",
119
130
  "./components/newsroom-topics-view": "./components/newsroom-topics-view.tsx",
131
+ "./components/notification-cards": "./components/notification-cards.tsx",
120
132
  "./components/notification-center": "./components/notification-center.tsx",
121
133
  "./components/papyrus-console-conversation": "./components/papyrus-console-conversation.tsx",
122
134
  "./components/papyrus-console-frame": "./components/papyrus-console-frame.tsx",
@@ -136,22 +148,30 @@
136
148
  "./components/reader-settings": "./components/reader-settings.ts",
137
149
  "./components/reader-theme-control": "./components/reader-theme-control.tsx",
138
150
  "./components/reference-add-entry": "./components/reference-add-entry.tsx",
151
+ "./components/reference-capture-client": "./components/reference-capture-client.ts",
152
+ "./components/reference-capture-panel": "./components/reference-capture-panel.tsx",
153
+ "./components/reference-conversation": "./components/reference-conversation.tsx",
139
154
  "./components/reference-curation-controls": "./components/reference-curation-controls.tsx",
140
155
  "./components/reference-cyclotron-priming": "./components/reference-cyclotron-priming.tsx",
141
156
  "./components/reference-cyclotron-status": "./components/reference-cyclotron-status.tsx",
142
157
  "./components/reference-cyclotron-suggestion": "./components/reference-cyclotron-suggestion.tsx",
158
+ "./components/reference-feed": "./components/reference-feed.tsx",
143
159
  "./components/reference-live-agreement": "./components/reference-live-agreement.tsx",
144
160
  "./components/reference-priming": "./components/reference-priming.tsx",
145
161
  "./components/reference-relevance-review": "./components/reference-relevance-review.tsx",
146
162
  "./components/reference-review-card": "./components/reference-review-card.tsx",
147
163
  "./components/reference-section-suggestion": "./components/reference-section-suggestion.tsx",
148
164
  "./components/reference-source-preview": "./components/reference-source-preview.tsx",
165
+ "./components/reference-stories": "./components/reference-stories.tsx",
166
+ "./components/references-page-loading": "./components/references-page-loading.tsx",
167
+ "./components/references-prefetch": "./components/references-prefetch.ts",
149
168
  "./components/settings-page": "./components/settings-page.tsx",
150
169
  "./components/signup-entries-panel": "./components/signup-entries-panel.tsx",
151
170
  "./components/staging-banner": "./components/staging-banner.tsx",
152
171
  "./components/story-reporting-trail-client": "./components/story-reporting-trail-client.ts",
153
172
  "./components/story-reporting-trail": "./components/story-reporting-trail.tsx",
154
173
  "./components/topic-steering-workspace": "./components/topic-steering-workspace.tsx",
174
+ "./components/ui/auto-grow-textarea": "./components/ui/auto-grow-textarea.tsx",
155
175
  "./components/ui/badge": "./components/ui/badge.tsx",
156
176
  "./components/ui/button-group": "./components/ui/button-group.tsx",
157
177
  "./components/ui/button": "./components/ui/button.tsx",
@@ -173,9 +193,13 @@
173
193
  "./components/use-blog-header-obstacles": "./components/use-blog-header-obstacles.ts",
174
194
  "./components/use-brand-fonts-ready": "./components/use-brand-fonts-ready.ts",
175
195
  "./components/use-console-visibility": "./components/use-console-visibility.ts",
196
+ "./components/use-conversation": "./components/use-conversation.ts",
176
197
  "./components/use-editorial-checks": "./components/use-editorial-checks.ts",
198
+ "./components/use-media-query": "./components/use-media-query.ts",
177
199
  "./components/use-near-viewport": "./components/use-near-viewport.ts",
178
200
  "./components/use-paged-content-item-versions": "./components/use-paged-content-item-versions.ts",
201
+ "./components/use-reference-preview-attachments": "./components/use-reference-preview-attachments.ts",
202
+ "./components/use-reference-ratings": "./components/use-reference-ratings.ts",
179
203
  "./components/use-resolved-papyrus-theme": "./components/use-resolved-papyrus-theme.ts",
180
204
  "./components/use-rhythm-overlay": "./components/use-rhythm-overlay.ts",
181
205
  "./components/wiki-concepts-view": "./components/wiki-concepts-view.tsx",
@@ -210,6 +234,7 @@
210
234
  "./lib/content-repository": "./lib/content-repository.ts",
211
235
  "./lib/content-source-context": "./lib/content-source-context.ts",
212
236
  "./lib/content-types": "./lib/content-types.ts",
237
+ "./lib/conversation": "./lib/conversation.ts",
213
238
  "./lib/curation-client": "./lib/curation-client.ts",
214
239
  "./lib/curation-delegation-helpers": "./lib/curation-delegation-helpers.ts",
215
240
  "./lib/curation-routes": "./lib/curation-routes.ts",
@@ -240,8 +265,10 @@
240
265
  "./lib/layout-scenarios": "./lib/layout-scenarios.ts",
241
266
  "./lib/layout-types": "./lib/layout-types.ts",
242
267
  "./lib/layout-warnings": "./lib/layout-warnings.ts",
268
+ "./lib/local-preview-feed-fixture": "./lib/local-preview-feed-fixture.ts",
243
269
  "./lib/local-preview-section-fixtures": "./lib/local-preview-section-fixtures.ts",
244
270
  "./lib/local-preview-seed": "./lib/local-preview-seed.ts",
271
+ "./lib/local-preview-synthetic-rejects": "./lib/local-preview-synthetic-rejects.ts",
245
272
  "./lib/local-preview-tenant": "./lib/local-preview-tenant.ts",
246
273
  "./lib/local-preview": "./lib/local-preview.ts",
247
274
  "./lib/markus-body": "./lib/markus-body.ts",
@@ -252,12 +279,16 @@
252
279
  "./lib/monitoring-client": "./lib/monitoring-client.ts",
253
280
  "./lib/monitoring-overview-fixture": "./lib/monitoring-overview-fixture.ts",
254
281
  "./lib/monitoring-overview": "./lib/monitoring-overview.ts",
282
+ "./lib/monitoring-paging": "./lib/monitoring-paging.ts",
283
+ "./lib/needs-me-items": "./lib/needs-me-items.ts",
284
+ "./lib/needs-me-ranking": "./lib/needs-me-ranking.ts",
255
285
  "./lib/news-desk-session": "./lib/news-desk-session.ts",
256
286
  "./lib/newsletter-api": "./lib/newsletter-api.ts",
257
287
  "./lib/newsletter-client": "./lib/newsletter-client.ts",
258
288
  "./lib/newsletter-fixture": "./lib/newsletter-fixture.ts",
259
289
  "./lib/newsletter-model": "./lib/newsletter-model.ts",
260
290
  "./lib/newspaper-layout": "./lib/newspaper-layout.ts",
291
+ "./lib/newsroom-all-pages": "./lib/newsroom-all-pages.ts",
261
292
  "./lib/newsroom-articles": "./lib/newsroom-articles.ts",
262
293
  "./lib/newsroom-assignments": "./lib/newsroom-assignments.ts",
263
294
  "./lib/newsroom-base-path": "./lib/newsroom-base-path.ts",
@@ -281,6 +312,7 @@
281
312
  "./lib/newsroom-section-routing": "./lib/newsroom-section-routing.ts",
282
313
  "./lib/newsroom-sections": "./lib/newsroom-sections.ts",
283
314
  "./lib/newsroom-topics": "./lib/newsroom-topics.ts",
315
+ "./lib/notification-feed": "./lib/notification-feed.ts",
284
316
  "./lib/oauth-redirect-priority": "./lib/oauth-redirect-priority.ts",
285
317
  "./lib/papyrus-chat-admission": "./lib/papyrus-chat-admission.ts",
286
318
  "./lib/papyrus-hosted-chat": "./lib/papyrus-hosted-chat.ts",
@@ -293,6 +325,7 @@
293
325
  "./lib/pretext-layout": "./lib/pretext-layout.ts",
294
326
  "./lib/priming-proof-report": "./lib/priming-proof-report.ts",
295
327
  "./lib/proposals-admin": "./lib/proposals-admin.ts",
328
+ "./lib/proposals-client": "./lib/proposals-client.ts",
296
329
  "./lib/prospectus-account-client": "./lib/prospectus-account-client.ts",
297
330
  "./lib/prospectus-publication-access": "./lib/prospectus-publication-access.ts",
298
331
  "./lib/prospectus-session": "./lib/prospectus-session.ts",
@@ -312,8 +345,12 @@
312
345
  "./lib/reader-static-params": "./lib/reader-static-params.ts",
313
346
  "./lib/reader-storage-url": "./lib/reader-storage-url.ts",
314
347
  "./lib/reader-subject": "./lib/reader-subject.ts",
348
+ "./lib/reference-capture": "./lib/reference-capture.ts",
315
349
  "./lib/reference-display": "./lib/reference-display.ts",
350
+ "./lib/reference-feed-cache": "./lib/reference-feed-cache.ts",
351
+ "./lib/reference-feed-ranking": "./lib/reference-feed-ranking.ts",
316
352
  "./lib/reference-policy": "./lib/reference-policy.ts",
353
+ "./lib/reference-preview": "./lib/reference-preview.ts",
317
354
  "./lib/reference-review-details": "./lib/reference-review-details.ts",
318
355
  "./lib/reference-review-request": "./lib/reference-review-request.ts",
319
356
  "./lib/reference-source-preview": "./lib/reference-source-preview.ts",
@@ -325,6 +362,7 @@
325
362
  "./lib/revalidate-prewarm": "./lib/revalidate-prewarm.ts",
326
363
  "./lib/revalidate-secret": "./lib/revalidate-secret.ts",
327
364
  "./lib/review-client": "./lib/review-client.ts",
365
+ "./lib/review-drafts": "./lib/review-drafts.ts",
328
366
  "./lib/review-fixture": "./lib/review-fixture.ts",
329
367
  "./lib/review-requests": "./lib/review-requests.ts",
330
368
  "./lib/robots-policy": "./lib/robots-policy.ts",
@@ -341,6 +379,9 @@
341
379
  "./lib/site-renderer": "./lib/site-renderer.ts",
342
380
  "./lib/site-section-suggestions": "./lib/site-section-suggestions.ts",
343
381
  "./lib/site-stack": "./lib/site-stack.ts",
382
+ "./lib/source-frameable": "./lib/source-frameable.ts",
383
+ "./lib/source-icon": "./lib/source-icon.ts",
384
+ "./lib/staff-groups": "./lib/staff-groups.ts",
344
385
  "./lib/staging-gate": "./lib/staging-gate.ts",
345
386
  "./lib/staging-gated-path": "./lib/staging-gated-path.ts",
346
387
  "./lib/staging-preview-object": "./lib/staging-preview-object.ts",
@@ -391,6 +432,8 @@
391
432
  "./app/api/newsroom/curation/context/route": "./app/api/newsroom/curation/context/route.ts",
392
433
  "./app/api/newsroom/curation/priming/route": "./app/api/newsroom/curation/priming/route.ts",
393
434
  "./app/api/newsroom/curation/publication/route": "./app/api/newsroom/curation/publication/route.ts",
435
+ "./app/api/newsroom/source-frameable/route": "./app/api/newsroom/source-frameable/route.ts",
436
+ "./app/api/newsroom/source-icon/route": "./app/api/newsroom/source-icon/route.ts",
394
437
  "./app/api/reader/comment/delete/route": "./app/api/reader/comment/delete/route.ts",
395
438
  "./app/api/reader/comment/edit/route": "./app/api/reader/comment/edit/route.ts",
396
439
  "./app/api/reader/comment/route": "./app/api/reader/comment/route.ts",
@@ -467,7 +510,7 @@
467
510
  "optional": true
468
511
  }
469
512
  },
470
- "version": "5.43.0-next.4",
513
+ "version": "5.43.0-next.41",
471
514
  "dependencies": {
472
515
  "@aws-amplify/adapter-nextjs": "^1.7.3",
473
516
  "@aws-crypto/sha256-js": "5.2.0",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.43.0-next.4",
2
+ "version": "5.43.0-next.41",
3
3
  "routes": [
4
4
  {
5
5
  "file": "app/%5F_preview/[[...path]]/route.ts",
@@ -285,6 +285,28 @@
285
285
  "runtime": "\"nodejs\""
286
286
  }
287
287
  },
288
+ {
289
+ "file": "app/api/newsroom/source-frameable/route.ts",
290
+ "hasDefault": false,
291
+ "exports": [
292
+ "GET"
293
+ ],
294
+ "config": {
295
+ "dynamic": "\"force-dynamic\"",
296
+ "runtime": "\"nodejs\""
297
+ }
298
+ },
299
+ {
300
+ "file": "app/api/newsroom/source-icon/route.ts",
301
+ "hasDefault": false,
302
+ "exports": [
303
+ "GET"
304
+ ],
305
+ "config": {
306
+ "dynamic": "\"force-dynamic\"",
307
+ "runtime": "\"nodejs\""
308
+ }
309
+ },
288
310
  {
289
311
  "file": "app/api/reader/comment/delete/route.ts",
290
312
  "hasDefault": false,
@@ -1,25 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
-
5
- /** Placeholder geometry for the overview while private records or access are unresolved. */
6
- export function NewsroomOverviewSkeleton() {
7
- return (
8
- <div aria-label="Loading newsroom overview" className="space-y-8 font-sans" data-newsroom-overview-skeleton role="status">
9
- <section className="newsroom-overview-feed-frame space-y-4 overflow-hidden rounded-xl border bg-card p-4" aria-label="Notification Center">
10
- <div className="h-6 w-48 rounded bg-muted" />
11
- <div className="h-4 w-3/4 max-w-xl rounded bg-muted" />
12
- <div className="h-4 w-2/3 max-w-lg rounded bg-muted" />
13
- <div className="grid gap-3 sm:grid-cols-2">
14
- {Array.from({ length: 4 }, (_, index) => <div className="h-28 rounded-xl border bg-card p-4" key={index}>
15
- <div className="h-4 w-2/3 rounded bg-muted" /><div className="mt-4 h-3 w-1/2 rounded bg-muted" />
16
- </div>)}
17
- </div>
18
- </section>
19
- <section aria-label="Needs attention" className="space-y-3">
20
- <div className="h-4 w-32 rounded bg-muted" />
21
- <div className="h-16 rounded-xl border bg-card p-4"><div className="h-4 w-1/2 rounded bg-muted" /><div className="mt-2 h-3 w-1/3 rounded bg-muted" /></div>
22
- </section>
23
- </div>
24
- );
25
- }