@anthusai/papyrus 5.41.0 → 5.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/amplify/functions/content-actions/handler.py +2 -2
- package/amplify/functions/monitoring-view/wire.js +6 -4
- package/amplify/functions/monitoring-view/wire.ts +6 -4
- package/amplify/site-backend-config.js +19 -0
- package/amplify/site-backend-config.ts +27 -0
- package/amplify/site-backend.js +5 -3
- package/amplify/site-backend.ts +5 -3
- package/package.json +1 -1
- package/routes.manifest.json +1 -1
|
@@ -359,8 +359,8 @@ def handler(event, context):
|
|
|
359
359
|
if field == "intakeEmailSubmissionReferences":
|
|
360
360
|
client, _claims = create_authoring_client()
|
|
361
361
|
try:
|
|
362
|
-
from papyrus_content.monitoring_view import
|
|
363
|
-
receipt_store =
|
|
362
|
+
from papyrus_content.monitoring_view import default_email_store_factory
|
|
363
|
+
receipt_store = default_email_store_factory(os.environ)()
|
|
364
364
|
return intake_email_submission_references(
|
|
365
365
|
client, arguments, event.get("identity") or {}, receipt_store=receipt_store)
|
|
366
366
|
except IntakeError as error:
|
|
@@ -19,11 +19,12 @@ export function monitoringViewParameterArn(region, account) {
|
|
|
19
19
|
* Environment and least-privilege IAM for the monitoring-view function. A site outside the monitoring
|
|
20
20
|
* account simply finds no parameter and the page says monitoring is not configured.
|
|
21
21
|
*/
|
|
22
|
-
export function wireMonitoringView(backend) {
|
|
22
|
+
export function wireMonitoringView(backend, emailMonitorId = "hn") {
|
|
23
23
|
const lambda = backend.monitoringView.resources.lambda;
|
|
24
24
|
const stack = Stack.of(lambda);
|
|
25
25
|
lambda.addEnvironment("PAPYRUS_GRAPHQL_ENDPOINT", backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl);
|
|
26
26
|
lambda.addEnvironment("PAPYRUS_MONITORING_TABLE_PARAMETER", MONITORING_TABLE_PARAMETER);
|
|
27
|
+
lambda.addEnvironment("PAPYRUS_EMAIL_MONITOR_ID", emailMonitorId);
|
|
27
28
|
lambda.addToRolePolicy(new PolicyStatement({
|
|
28
29
|
effect: Effect.ALLOW,
|
|
29
30
|
actions: ["ssm:GetParameter"],
|
|
@@ -41,13 +42,14 @@ export function wireMonitoringView(backend) {
|
|
|
41
42
|
effect: Effect.ALLOW,
|
|
42
43
|
actions: ["dynamodb:PutItem"],
|
|
43
44
|
resources: monitoringViewTableArns(stack.region, stack.account).slice(0, 1),
|
|
44
|
-
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [
|
|
45
|
+
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [`MONITOR#${emailMonitorId}`] } },
|
|
45
46
|
}));
|
|
46
47
|
}
|
|
47
48
|
/** Lets the authenticated Reference-intake action verify a selected email receipt. */
|
|
48
|
-
export function wireEmailReferenceIntake(lambda) {
|
|
49
|
+
export function wireEmailReferenceIntake(lambda, emailMonitorId = "hn") {
|
|
49
50
|
const stack = Stack.of(lambda);
|
|
50
51
|
lambda.addEnvironment("PAPYRUS_MONITORING_TABLE_PARAMETER", MONITORING_TABLE_PARAMETER);
|
|
52
|
+
lambda.addEnvironment("PAPYRUS_EMAIL_MONITOR_ID", emailMonitorId);
|
|
51
53
|
lambda.addToRolePolicy(new PolicyStatement({
|
|
52
54
|
effect: Effect.ALLOW,
|
|
53
55
|
actions: ["ssm:GetParameter"],
|
|
@@ -57,6 +59,6 @@ export function wireEmailReferenceIntake(lambda) {
|
|
|
57
59
|
effect: Effect.ALLOW,
|
|
58
60
|
actions: MONITORING_VIEW_TABLE_ACTIONS,
|
|
59
61
|
resources: monitoringViewTableArns(stack.region, stack.account).slice(0, 1),
|
|
60
|
-
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [
|
|
62
|
+
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [`MONITOR#${emailMonitorId}`] } },
|
|
61
63
|
}));
|
|
62
64
|
}
|
|
@@ -25,11 +25,12 @@ export function monitoringViewParameterArn(region: string, account: string): str
|
|
|
25
25
|
* Environment and least-privilege IAM for the monitoring-view function. A site outside the monitoring
|
|
26
26
|
* account simply finds no parameter and the page says monitoring is not configured.
|
|
27
27
|
*/
|
|
28
|
-
export function wireMonitoringView(backend: any): void {
|
|
28
|
+
export function wireMonitoringView(backend: any, emailMonitorId = "hn"): void {
|
|
29
29
|
const lambda = backend.monitoringView.resources.lambda as LambdaFunction;
|
|
30
30
|
const stack = Stack.of(lambda);
|
|
31
31
|
lambda.addEnvironment("PAPYRUS_GRAPHQL_ENDPOINT", backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl as string);
|
|
32
32
|
lambda.addEnvironment("PAPYRUS_MONITORING_TABLE_PARAMETER", MONITORING_TABLE_PARAMETER);
|
|
33
|
+
lambda.addEnvironment("PAPYRUS_EMAIL_MONITOR_ID", emailMonitorId);
|
|
33
34
|
lambda.addToRolePolicy(
|
|
34
35
|
new PolicyStatement({
|
|
35
36
|
effect: Effect.ALLOW,
|
|
@@ -52,15 +53,16 @@ export function wireMonitoringView(backend: any): void {
|
|
|
52
53
|
effect: Effect.ALLOW,
|
|
53
54
|
actions: ["dynamodb:PutItem"],
|
|
54
55
|
resources: monitoringViewTableArns(stack.region, stack.account).slice(0, 1),
|
|
55
|
-
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [
|
|
56
|
+
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [`MONITOR#${emailMonitorId}`] } },
|
|
56
57
|
}),
|
|
57
58
|
);
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/** Lets the authenticated Reference-intake action verify a selected email receipt. */
|
|
61
|
-
export function wireEmailReferenceIntake(lambda: LambdaFunction): void {
|
|
62
|
+
export function wireEmailReferenceIntake(lambda: LambdaFunction, emailMonitorId = "hn"): void {
|
|
62
63
|
const stack = Stack.of(lambda);
|
|
63
64
|
lambda.addEnvironment("PAPYRUS_MONITORING_TABLE_PARAMETER", MONITORING_TABLE_PARAMETER);
|
|
65
|
+
lambda.addEnvironment("PAPYRUS_EMAIL_MONITOR_ID", emailMonitorId);
|
|
64
66
|
lambda.addToRolePolicy(
|
|
65
67
|
new PolicyStatement({
|
|
66
68
|
effect: Effect.ALLOW,
|
|
@@ -73,7 +75,7 @@ export function wireEmailReferenceIntake(lambda: LambdaFunction): void {
|
|
|
73
75
|
effect: Effect.ALLOW,
|
|
74
76
|
actions: MONITORING_VIEW_TABLE_ACTIONS,
|
|
75
77
|
resources: monitoringViewTableArns(stack.region, stack.account).slice(0, 1),
|
|
76
|
-
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [
|
|
78
|
+
conditions: { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": [`MONITOR#${emailMonitorId}`] } },
|
|
77
79
|
}),
|
|
78
80
|
);
|
|
79
81
|
}
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
export const MAXIMUM_HTML_S_MAXAGE_SECONDS = 86400;
|
|
2
|
+
const MONITOR_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
3
|
+
export function validateMonitoringConfig(monitoring) {
|
|
4
|
+
if (monitoring === undefined)
|
|
5
|
+
return [];
|
|
6
|
+
if (typeof monitoring !== "object" || monitoring === null || Array.isArray(monitoring)) {
|
|
7
|
+
return ["monitoring must be an object"];
|
|
8
|
+
}
|
|
9
|
+
const config = monitoring;
|
|
10
|
+
if (config.emailMonitorId !== undefined
|
|
11
|
+
&& (typeof config.emailMonitorId !== "string" || !MONITOR_ID_PATTERN.test(config.emailMonitorId))) {
|
|
12
|
+
return ["monitoring.emailMonitorId must be a lowercase monitor id (1-63 letters, digits, or hyphens)"];
|
|
13
|
+
}
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
export function assertValidMonitoringConfig(monitoring) {
|
|
17
|
+
const problems = validateMonitoringConfig(monitoring);
|
|
18
|
+
if (problems.length > 0)
|
|
19
|
+
throw new Error(`Invalid backend.monitoring: ${problems.join("; ")}`);
|
|
20
|
+
}
|
|
2
21
|
const CLOUDFRONT_DISTRIBUTION_ARN = /^arn:aws[a-z-]*:cloudfront::\d{12}:distribution\/[A-Z0-9]+$/;
|
|
3
22
|
function isRelativePathWithoutParentSegments(value) {
|
|
4
23
|
if (value === "" || value.startsWith("/") || value.includes("\\"))
|
|
@@ -40,6 +40,31 @@ export type PapyrusPublicationCacheConfig = {
|
|
|
40
40
|
|
|
41
41
|
export const MAXIMUM_HTML_S_MAXAGE_SECONDS = 86400;
|
|
42
42
|
|
|
43
|
+
export type PapyrusMonitoringConfig = {
|
|
44
|
+
/** Existing shared Monitoring partition that stores this site's private email receipts. */
|
|
45
|
+
emailMonitorId?: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const MONITOR_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
49
|
+
|
|
50
|
+
export function validateMonitoringConfig(monitoring: unknown): string[] {
|
|
51
|
+
if (monitoring === undefined) return [];
|
|
52
|
+
if (typeof monitoring !== "object" || monitoring === null || Array.isArray(monitoring)) {
|
|
53
|
+
return ["monitoring must be an object"];
|
|
54
|
+
}
|
|
55
|
+
const config = monitoring as { emailMonitorId?: unknown };
|
|
56
|
+
if (config.emailMonitorId !== undefined
|
|
57
|
+
&& (typeof config.emailMonitorId !== "string" || !MONITOR_ID_PATTERN.test(config.emailMonitorId))) {
|
|
58
|
+
return ["monitoring.emailMonitorId must be a lowercase monitor id (1-63 letters, digits, or hyphens)"];
|
|
59
|
+
}
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function assertValidMonitoringConfig(monitoring: unknown): void {
|
|
64
|
+
const problems = validateMonitoringConfig(monitoring);
|
|
65
|
+
if (problems.length > 0) throw new Error(`Invalid backend.monitoring: ${problems.join("; ")}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
43
68
|
export type PapyrusPublicationConfig = {
|
|
44
69
|
kind: "s3-projection";
|
|
45
70
|
/** Site repo path (relative, `.py`) of the SiteProjector bundled into content-actions as `site_projector`. */
|
|
@@ -138,6 +163,8 @@ export type PapyrusSiteBackendConfig = {
|
|
|
138
163
|
*/
|
|
139
164
|
productionAppId?: string;
|
|
140
165
|
auth?: PapyrusAuthConfig;
|
|
166
|
+
/** Shared Monitoring partition used by private email intake for this publication. */
|
|
167
|
+
monitoring?: PapyrusMonitoringConfig;
|
|
141
168
|
/**
|
|
142
169
|
* Maximum number of data model nested stacks CloudFormation creates at once.
|
|
143
170
|
* Stacks are chained in waves of this size so a new AWS account is not hit
|
package/amplify/site-backend.js
CHANGED
|
@@ -14,7 +14,7 @@ import { planRenditions } from "./publication/renditions-settings.js";
|
|
|
14
14
|
import { addProjectionLeaseAccess } from "./publication/projection-lease.js";
|
|
15
15
|
import { contentActionsPublicationWiring, planS3ProjectionBackend } from "./publication/s3-projection-settings.js";
|
|
16
16
|
import { rebuildTriggerSettings } from "./rebuild-trigger-settings.js";
|
|
17
|
-
import { assertValidPublicationConfig } from "./site-backend-config.js";
|
|
17
|
+
import { assertValidMonitoringConfig, assertValidPublicationConfig } from "./site-backend-config.js";
|
|
18
18
|
import { revalidateSecretReadStatement } from "./revalidate-secret-policy.js";
|
|
19
19
|
import { revalidateDistributionEnvironment, revalidateInvalidationStatement, validateRevalidateDistributionIds, } from "./revalidate-invalidation-settings.js";
|
|
20
20
|
import { addInvalidationPathAlarm } from "./publication/invalidation-alarm.js";
|
|
@@ -87,6 +87,8 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
87
87
|
const publication = resolveSitePublication(site, activeBrand?.renderer?.kind);
|
|
88
88
|
if (publication !== undefined)
|
|
89
89
|
assertValidPublicationConfig(publication);
|
|
90
|
+
assertValidMonitoringConfig(site.monitoring);
|
|
91
|
+
const emailMonitorId = site.monitoring?.emailMonitorId ?? "hn";
|
|
90
92
|
const publicationPlan = planS3ProjectionBackend(publication);
|
|
91
93
|
const renditionsPlan = planRenditions(publication, process.cwd());
|
|
92
94
|
setSiteFilesForContentActionsBundle(publicationPlan.enabled ? publicationPlan.siteFiles : undefined);
|
|
@@ -336,7 +338,7 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
336
338
|
// and publication to this deployment's pool and existing API endpoint.
|
|
337
339
|
contentActionsLambda.addEnvironment("PAPYRUS_USER_POOL_ISSUER", `https://cognito-idp.${Stack.of(contentActionsLambda).region}.amazonaws.com/${backend.auth.resources.userPool.userPoolId}`);
|
|
338
340
|
contentActionsLambda.addEnvironment("PAPYRUS_GRAPHQL_ENDPOINT", backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl);
|
|
339
|
-
wireEmailReferenceIntake(contentActionsLambda);
|
|
341
|
+
wireEmailReferenceIntake(contentActionsLambda, emailMonitorId);
|
|
340
342
|
contentActionsLambda.addToRolePolicy(new PolicyStatement({
|
|
341
343
|
actions: ["appsync:GraphQL"],
|
|
342
344
|
resources: ["*"],
|
|
@@ -627,7 +629,7 @@ export function defineSiteBackend(papyrusSite) {
|
|
|
627
629
|
},
|
|
628
630
|
});
|
|
629
631
|
wireEditorialChecks(backend);
|
|
630
|
-
wireMonitoringView(backend);
|
|
632
|
+
wireMonitoringView(backend, emailMonitorId);
|
|
631
633
|
wireAutomationView(backend);
|
|
632
634
|
wirePlugins(backend, plugins, contentActionsLambda);
|
|
633
635
|
return backend;
|
package/amplify/site-backend.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { planRenditions } from "./publication/renditions-settings";
|
|
|
17
17
|
import { addProjectionLeaseAccess } from "./publication/projection-lease";
|
|
18
18
|
import { contentActionsPublicationWiring, planS3ProjectionBackend } from "./publication/s3-projection-settings";
|
|
19
19
|
import { rebuildTriggerSettings } from "./rebuild-trigger-settings";
|
|
20
|
-
import { assertValidPublicationConfig } from "./site-backend-config";
|
|
20
|
+
import { assertValidMonitoringConfig, assertValidPublicationConfig } from "./site-backend-config";
|
|
21
21
|
import { revalidateSecretReadStatement } from "./revalidate-secret-policy";
|
|
22
22
|
import {
|
|
23
23
|
revalidateDistributionEnvironment,
|
|
@@ -108,6 +108,8 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
108
108
|
};
|
|
109
109
|
const publication = resolveSitePublication(site, activeBrand?.renderer?.kind);
|
|
110
110
|
if (publication !== undefined) assertValidPublicationConfig(publication);
|
|
111
|
+
assertValidMonitoringConfig(site.monitoring);
|
|
112
|
+
const emailMonitorId = site.monitoring?.emailMonitorId ?? "hn";
|
|
111
113
|
const publicationPlan = planS3ProjectionBackend(publication);
|
|
112
114
|
const renditionsPlan = planRenditions(publication, process.cwd());
|
|
113
115
|
setSiteFilesForContentActionsBundle(publicationPlan.enabled ? publicationPlan.siteFiles : undefined);
|
|
@@ -429,7 +431,7 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
429
431
|
"PAPYRUS_GRAPHQL_ENDPOINT",
|
|
430
432
|
backend.data.resources.cfnResources.cfnGraphqlApi.attrGraphQlUrl,
|
|
431
433
|
);
|
|
432
|
-
wireEmailReferenceIntake(contentActionsLambda);
|
|
434
|
+
wireEmailReferenceIntake(contentActionsLambda, emailMonitorId);
|
|
433
435
|
contentActionsLambda.addToRolePolicy(
|
|
434
436
|
new PolicyStatement({
|
|
435
437
|
actions: ["appsync:GraphQL"],
|
|
@@ -773,7 +775,7 @@ export function defineSiteBackend(papyrusSite: PapyrusSite) {
|
|
|
773
775
|
},
|
|
774
776
|
});
|
|
775
777
|
wireEditorialChecks(backend);
|
|
776
|
-
wireMonitoringView(backend);
|
|
778
|
+
wireMonitoringView(backend, emailMonitorId);
|
|
777
779
|
wireAutomationView(backend);
|
|
778
780
|
wirePlugins(backend, plugins, contentActionsLambda);
|
|
779
781
|
|
package/package.json
CHANGED
package/routes.manifest.json
CHANGED