Refactor code structure and optimize performance across multiple modules
This commit is contained in:
14
devops/offline/fixtures/notifier/artifact-hashes.json
Normal file
14
devops/offline/fixtures/notifier/artifact-hashes.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"hash_algorithm": "blake3-256",
|
||||
"entries": [
|
||||
{ "path": "docs/notifications/schemas/notify-schemas-catalog.json", "digest": "34e8655b0c7ca70c844d4b9aee56bdd7bd30b6a8666d2af75a70856b16f5605d" },
|
||||
{ "path": "docs/notifications/schemas/notify-schemas-catalog.dsse.json", "digest": "7c537ff728312cefb0769568bd376adc2bd79f6926173bf21f50c873902133dc" },
|
||||
{ "path": "docs/notifications/gaps-nr1-nr10.md", "digest": "b889dfd19a9d0a0f7bafb958135fde151e63c1e5259453d592d6519ae1667819" },
|
||||
{ "path": "docs/notifications/fixtures/rendering/index.ndjson", "digest": "3a41e62687b6e04f50e86ea74706eeae28eef666d7c4dbb5dc2281e6829bf41a" },
|
||||
{ "path": "docs/notifications/fixtures/redaction/sample.json", "digest": "dd4eefc8dded5d6f46c832e959ba0eef95ee8b77f10ac0aae90f7c89ad42906c" },
|
||||
{ "path": "docs/notifications/operations/dashboards/notify-slo.json", "digest": "8b380cb5491727a3ec69d50789f5522ac66c97804bebbf7de326568e52b38fa9" },
|
||||
{ "path": "docs/notifications/operations/alerts/notify-slo-alerts.yaml", "digest": "2c3b702c42d3e860c7f4e51d577f77961e982e1d233ef5ec392cba5414a0056d" },
|
||||
{ "path": "offline/notifier/notify-kit.manifest.json", "digest": "15e0b2f670e6b8089c6c960e354f16ba8201d993a077a28794a30b8d1cb23e9a" },
|
||||
{ "path": "offline/notifier/notify-kit.manifest.dsse.json", "digest": "68742f4e5bd202afe2cc90964d51fea7971395f3e57a875ae7111dcbb760321e" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"payloadType": "application/vnd.notify.manifest+json",
|
||||
"payload": "ewogICJzY2hlbWFfdmVyc2lvbiI6ICJ2MS4wIiwKICAiZ2VuZXJhdGVkX2F0IjogIjIwMjUtMTItMDRUMDA6MDA6MDBaIiwKICAidGVuYW50X3Njb3BlIjogIioiLAogICJlbnZpcm9ubWVudCI6ICJvZmZsaW5lIiwKICAiYXJ0aWZhY3RzIjogWwogICAgeyAibmFtZSI6ICJzY2hlbWEtY2F0YWxvZyIsICJwYXRoIjogImRvY3Mvbm90aWZpY2F0aW9ucy9zY2hlbWFzL25vdGlmeS1zY2hlbWFzLWNhdGFsb2cuanNvbiIsICJkaWdlc3QiOiAiMzRlODY1NWIwYzdjYTcwYzg0NGQ0YjlhZWU1NmJkZDdiZDMwYjZhODY2NmQyYWY3NWE3MDg1NmIxNmY1NjA1ZCIgfSwKICAgIHsgIm5hbWUiOiAic2NoZW1hLWNhdGFsb2ctZHNzZSIsICJwYXRoIjogImRvY3Mvbm90aWZpY2F0aW9ucy9zY2hlbWFzL25vdGlmeS1zY2hlbWFzLWNhdGFsb2cuZHNzZS5qc29uIiwgImRpZ2VzdCI6ICI3YzUzN2ZmNzI4MzEyY2VmYjA3Njk1NjhiZDM3NmFkYzJiZDc5ZjY5MjYxNzNiZjIxZjUwYzg3MzkwMjEzM2RjIiB9LAogICAgeyAibmFtZSI6ICJydWxlcyIsICJwYXRoIjogImRvY3Mvbm90aWZpY2F0aW9ucy9nYXBzLW5yMS1ucjEwLm1kIiwgImRpZ2VzdCI6ICJiODg5ZGZkMTlhOWQwYTBmN2JhZmI5NTgxMzVmZGUxNTFlNjNjMWU1MjU5NDUzZDU5MmQ2NTE5YWUxNjY3ODE5IiB9LAogICAgeyAibmFtZSI6ICJmaXh0dXJlcy1yZW5kZXJpbmciLCAicGF0aCI6ICJkb2NzL25vdGlmaWNhdGlvbnMvZml4dHVyZXMvcmVuZGVyaW5nL2luZGV4Lm5kanNvbiIsICJkaWdlc3QiOiAiM2E0MWU2MjY4N2I2ZTA0ZjUwZTg2ZWE3NDcwNmVlYWUyOGVlZjY2NmQ3YzRkYmI1ZGMyMjgxZTY4MjliZjQxYSIgfSwKICAgIHsgIm5hbWUiOiAiZml4dHVyZXMtcmVkYWN0aW9uIiwgInBhdGgiOiAiZG9jcy9ub3RpZmljYXRpb25zL2ZpeHR1cmVzL3JlZGFjdGlvbi9zYW1wbGUuanNvbiIsICJkaWdlc3QiOiAiZGQ0ZWVmYzhkZGVkNWQ2ZjQ2YzgzMmU5NTliYTBlZWY5NWVlOGI3N2YxMGFjMGFhZTkwZjdjODlhZDQyOTA2YyIgfSwKICAgIHsgIm5hbWUiOiAiZGFzaGJvYXJkcyIsICJwYXRoIjogImRvY3Mvbm90aWZpY2F0aW9ucy9vcGVyYXRpb25zL2Rhc2hib2FyZHMvbm90aWZ5LXNsby5qc29uIiwgImRpZ2VzdCI6ICI4YjM4MGNiNTQ5MTcyN2EzZWM2OWQ1MDc4OWY1NTIyYWM2NmM5NzgwNGJlYmJmN2RlMzI2NTY4ZTUyYjM4ZmE5IiB9LAogICAgeyAibmFtZSI6ICJhbGVydHMiLCAicGF0aCI6ICJkb2NzL25vdGlmaWNhdGlvbnMvb3BlcmF0aW9ucy9hbGVydHMvbm90aWZ5LXNsby1hbGVydHMueWFtbCIsICJkaWdlc3QiOiAiMmMzYjcwMmM0MmQzZTg2MGM3ZjRlNTFkNTc3Zjc3OTYxZTk4MmUxZDIzM2VmNWVjMzkyY2JhNTQxNGEwMDU2ZCIgfQogIF0sCiAgImhhc2hfYWxnb3JpdGhtIjogImJsYWtlMy0yNTYiLAogICJjYW5vbmljYWxpemF0aW9uIjogImpzb24tbm9ybWFsaXplZC11dGY4Igp9Cg==",
|
||||
"signatures": [
|
||||
{
|
||||
"sig": "DZwohxh6AOAP7Qf9geoZjw2jTXVU3rR8sYw4mgKpMu0=",
|
||||
"keyid": "notify-dev-hmac-001",
|
||||
"signedAt": "2025-12-04T21:13:10+00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
17
devops/offline/fixtures/notifier/notify-kit.manifest.json
Normal file
17
devops/offline/fixtures/notifier/notify-kit.manifest.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"schema_version": "v1.0",
|
||||
"generated_at": "2025-12-04T00:00:00Z",
|
||||
"tenant_scope": "*",
|
||||
"environment": "offline",
|
||||
"artifacts": [
|
||||
{ "name": "schema-catalog", "path": "docs/notifications/schemas/notify-schemas-catalog.json", "digest": "34e8655b0c7ca70c844d4b9aee56bdd7bd30b6a8666d2af75a70856b16f5605d" },
|
||||
{ "name": "schema-catalog-dsse", "path": "docs/notifications/schemas/notify-schemas-catalog.dsse.json", "digest": "7c537ff728312cefb0769568bd376adc2bd79f6926173bf21f50c873902133dc" },
|
||||
{ "name": "rules", "path": "docs/notifications/gaps-nr1-nr10.md", "digest": "b889dfd19a9d0a0f7bafb958135fde151e63c1e5259453d592d6519ae1667819" },
|
||||
{ "name": "fixtures-rendering", "path": "docs/notifications/fixtures/rendering/index.ndjson", "digest": "3a41e62687b6e04f50e86ea74706eeae28eef666d7c4dbb5dc2281e6829bf41a" },
|
||||
{ "name": "fixtures-redaction", "path": "docs/notifications/fixtures/redaction/sample.json", "digest": "dd4eefc8dded5d6f46c832e959ba0eef95ee8b77f10ac0aae90f7c89ad42906c" },
|
||||
{ "name": "dashboards", "path": "docs/notifications/operations/dashboards/notify-slo.json", "digest": "8b380cb5491727a3ec69d50789f5522ac66c97804bebbf7de326568e52b38fa9" },
|
||||
{ "name": "alerts", "path": "docs/notifications/operations/alerts/notify-slo-alerts.yaml", "digest": "2c3b702c42d3e860c7f4e51d577f77961e982e1d233ef5ec392cba5414a0056d" }
|
||||
],
|
||||
"hash_algorithm": "blake3-256",
|
||||
"canonicalization": "json-normalized-utf8"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-expiry-warning-email-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "email",
|
||||
"key": "tmpl-attest-expiry-warning",
|
||||
"locale": "en-us",
|
||||
"renderMode": "html",
|
||||
"format": "email",
|
||||
"description": "Expiry warning for attestations approaching their expiration window.",
|
||||
"body": "<h2>Attestation expiry notice</h2>\n<p>The attestation for <code>{{payload.subject.repository}}</code> (digest {{payload.subject.digest}}) expires on <strong>{{payload.attestation.expiresAt}}</strong>.</p>\n<ul>\n <li>Issued: {{payload.attestation.issuedAt}}</li>\n <li>Signer: <code>{{payload.signer.kid}}</code> ({{payload.signer.algorithm}})</li>\n <li>Time remaining: {{expires_in payload.attestation.expiresAt event.ts}}</li>\n</ul>\n<p>Please rotate the attestation before expiry using <a href=\"{{payload.links.docs}}\">these instructions</a>.</p>\n<p>Console: <a href=\"{{payload.links.console}}\">{{payload.links.console}}</a></p>\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-expiry-warning-slack-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "slack",
|
||||
"key": "tmpl-attest-expiry-warning",
|
||||
"locale": "en-us",
|
||||
"renderMode": "markdown",
|
||||
"format": "slack",
|
||||
"description": "Slack reminder for attestations approaching their expiration window.",
|
||||
"body": ":warning: Attestation for `{{payload.subject.digest}}` expires {{expires_in payload.attestation.expiresAt event.ts}}\nRepo: `{{payload.subject.repository}}`{{#if payload.subject.tag}} ({{payload.subject.tag}}){{/if}}\nSigner: `{{fingerprint payload.signer.kid}}` ({{payload.signer.algorithm}})\nIssued: {{payload.attestation.issuedAt}} · Expires: {{payload.attestation.expiresAt}}\nRenewal steps: {{link \"Docs\" payload.links.docs}} · Console: {{link \"Open\" payload.links.console}}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-16"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-key-rotation-email-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "email",
|
||||
"key": "tmpl-attest-key-rotation",
|
||||
"locale": "en-us",
|
||||
"renderMode": "html",
|
||||
"format": "email",
|
||||
"description": "Email bulletin for attestation key rotation or revocation events.",
|
||||
"body": "<h2>Attestation key rotation notice</h2>\n<p>Authority rotated or revoked signing keys at {{payload.rotation.executedAt}}.</p>\n<ul>\n <li>Rotation batch: {{payload.rotation.batchId}}</li>\n <li>Impacted services: {{payload.rotation.impactedServices}}</li>\n <li>Reason: {{payload.rotation.reason}}</li>\n</ul>\n<p>Recommended action: {{payload.recommendation}}</p>\n<p>Docs: <a href=\"{{payload.links.docs}}\">Rotation playbook</a></p>\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-key-rotation-webhook-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "webhook",
|
||||
"key": "tmpl-attest-key-rotation",
|
||||
"locale": "en-us",
|
||||
"renderMode": "json",
|
||||
"format": "webhook",
|
||||
"description": "Webhook payload for attestation key rotation/revocation events.",
|
||||
"body": "{\n \"event\": \"authority.keys.rotated\",\n \"tenantId\": \"{{event.tenant}}\",\n \"batchId\": \"{{payload.rotation.batchId}}\",\n \"executedAt\": \"{{payload.rotation.executedAt}}\",\n \"impactedServices\": \"{{payload.rotation.impactedServices}}\",\n \"reason\": \"{{payload.rotation.reason}}\",\n \"links\": {\n \"docs\": \"{{payload.links.docs}}\",\n \"console\": \"{{payload.links.console}}\"\n }\n}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-transparency-anomaly-slack-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "slack",
|
||||
"key": "tmpl-attest-transparency-anomaly",
|
||||
"locale": "en-us",
|
||||
"renderMode": "markdown",
|
||||
"format": "slack",
|
||||
"description": "Slack alert for transparency witness anomalies.",
|
||||
"body": ":warning: Transparency anomaly detected for `{{payload.subject.digest}}`\nWitness: `{{payload.transparency.witnessId}}` ({{payload.transparency.classification}})\nRekor index: {{payload.transparency.rekorIndex}}\nAnomaly window: {{payload.transparency.windowStart}} → {{payload.transparency.windowEnd}}\nRecommended action: {{payload.recommendation}}\nConsole details: {{link \"Open in Console\" payload.links.console}}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-transparency-anomaly-webhook-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "webhook",
|
||||
"key": "tmpl-attest-transparency-anomaly",
|
||||
"locale": "en-us",
|
||||
"renderMode": "json",
|
||||
"format": "webhook",
|
||||
"description": "Webhook payload for Rekor transparency anomalies.",
|
||||
"body": "{\n \"event\": \"attestor.transparency.anomaly\",\n \"tenantId\": \"{{event.tenant}}\",\n \"subjectDigest\": \"{{payload.subject.digest}}\",\n \"witnessId\": \"{{payload.transparency.witnessId}}\",\n \"classification\": \"{{payload.transparency.classification}}\",\n \"rekorIndex\": {{payload.transparency.rekorIndex}},\n \"window\": {\n \"start\": \"{{payload.transparency.windowStart}}\",\n \"end\": \"{{payload.transparency.windowEnd}}\"\n },\n \"links\": {\n \"console\": \"{{payload.links.console}}\",\n \"rekor\": \"{{payload.links.rekor}}\"\n },\n \"recommendation\": \"{{payload.recommendation}}\"\n}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-verify-fail-email-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "email",
|
||||
"key": "tmpl-attest-verify-fail",
|
||||
"locale": "en-us",
|
||||
"renderMode": "html",
|
||||
"format": "email",
|
||||
"description": "Email notice for attestation verification failures.",
|
||||
"body": "<h2>Attestation verification failure</h2>\n<p>The attestation for <code>{{payload.subject.repository}}</code> (digest {{payload.subject.digest}}) failed verification at {{event.ts}}.</p>\n<ul>\n <li>Reason: <code>{{payload.failure.reasonCode}}</code> — {{payload.failure.reason}}</li>\n <li>Signer: <code>{{payload.signer.kid}}</code> ({{payload.signer.algorithm}})</li>\n <li>Rekor entry: <a href=\"{{payload.links.rekor}}\">{{payload.links.rekor}}</a></li>\n <li>Last valid attestation: <a href=\"{{payload.links.console}}\">Console report</a></li>\n</ul>\n<p>{{payload.recommendation}}</p>\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-verify-fail-slack-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "slack",
|
||||
"key": "tmpl-attest-verify-fail",
|
||||
"locale": "en-us",
|
||||
"renderMode": "markdown",
|
||||
"format": "slack",
|
||||
"description": "Slack alert for attestation verification failures with Rekor traceability.",
|
||||
"body": ":rotating_light: {{attestation_status_badge payload.failure.status}} verification failed for `{{payload.subject.digest}}`\nSigner: `{{fingerprint payload.signer.kid}}` ({{payload.signer.algorithm}})\nReason: `{{payload.failure.reasonCode}}` — {{payload.failure.reason}}\nLast valid attestation: {{link \"Console\" payload.links.console}}\nRekor entry: {{link \"Transparency log\" payload.links.rekor}}\nRecommended action: {{payload.recommendation}}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-attest-verify-fail-webhook-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "webhook",
|
||||
"key": "tmpl-attest-verify-fail",
|
||||
"locale": "en-us",
|
||||
"renderMode": "json",
|
||||
"format": "webhook",
|
||||
"description": "JSON payload for Pager/SOC integrations on attestation verification failures.",
|
||||
"body": "{\n \"event\": \"attestor.verification.failed\",\n \"tenantId\": \"{{event.tenant}}\",\n \"subjectDigest\": \"{{payload.subject.digest}}\",\n \"repository\": \"{{payload.subject.repository}}\",\n \"reasonCode\": \"{{payload.failure.reasonCode}}\",\n \"reason\": \"{{payload.failure.reason}}\",\n \"signer\": {\n \"kid\": \"{{payload.signer.kid}}\",\n \"algorithm\": \"{{payload.signer.algorithm}}\"\n },\n \"rekor\": {\n \"url\": \"{{payload.links.rekor}}\",\n \"uuid\": \"{{payload.rekor.uuid}}\",\n \"index\": {{payload.rekor.index}}\n },\n \"recommendation\": \"{{payload.recommendation}}\"\n}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-api-deprecation-email-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "email",
|
||||
"key": "tmpl-api-deprecation",
|
||||
"locale": "en-us",
|
||||
"renderMode": "html",
|
||||
"format": "email",
|
||||
"description": "Email notification for retiring Notifier API versions.",
|
||||
"body": "<h2>Notifier API deprecation notice</h2>\n<p>The Notifier API v1 endpoints are scheduled for sunset on <strong>{{metadata.sunset}}</strong>.</p>\n<ul>\n <li>Paths affected: {{metadata.paths}}</li>\n <li>Scope: notify.*</li>\n <li>Replacement: {{metadata.replacement}}</li>\n</ul>\n<p>Action: {{metadata.action}}</p>\n<p>Details: <a href=\"{{metadata.docs}}\">Deprecation bulletin</a></p>\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-17"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-api-deprecation-slack-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "slack",
|
||||
"key": "tmpl-api-deprecation",
|
||||
"locale": "en-us",
|
||||
"renderMode": "markdown",
|
||||
"format": "slack",
|
||||
"description": "Slack notice for retiring Notifier API versions.",
|
||||
"body": ":warning: Notifier API v1 is being deprecated.\nSunset: {{metadata.sunset}}\nPaths affected: {{metadata.paths}}\nDocs: {{link \"Deprecation details\" metadata.docs}}\nAction: {{metadata.action}}\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-17"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-risk-profile-state-email-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "email",
|
||||
"key": "tmpl-risk-profile-state",
|
||||
"locale": "en-us",
|
||||
"renderMode": "html",
|
||||
"format": "email",
|
||||
"description": "Email notice when risk profiles are published, deprecated, or thresholds change.",
|
||||
"body": "<h2>Risk profile update</h2>\n<p>Profile <strong>{{payload.profile.id}}</strong> is now <strong>{{payload.state}}</strong> (version {{payload.profile.version}}).</p>\n<ul>\n <li>Thresholds: {{payload.thresholds}}</li>\n <li>Owner: {{payload.owner}}</li>\n <li>Effective at: {{payload.effectiveAt}}</li>\n</ul>\n<p>Notes: {{payload.notes}}</p>\n<p>Console: <a href=\"{{payload.links.console}}\">View profile</a></p>\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-24"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-risk-profile-state-slack-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "slack",
|
||||
"key": "tmpl-risk-profile-state",
|
||||
"locale": "en-us",
|
||||
"renderMode": "markdown",
|
||||
"format": "json",
|
||||
"description": "Slack notice when risk profiles publish, deprecate, or thresholds change.",
|
||||
"body": "*Risk profile {{payload.profile.id}}* is now *{{payload.state}}* (v{{payload.profile.version}})\n• thresholds: {{payload.thresholds}}\n• owner: {{payload.owner}}\n• effective: {{payload.effectiveAt}}\n<{{payload.links.console}}|View profile>",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-24"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-risk-severity-change-email-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "email",
|
||||
"key": "tmpl-risk-severity-change",
|
||||
"locale": "en-us",
|
||||
"renderMode": "html",
|
||||
"format": "email",
|
||||
"description": "Email notice for risk severity escalation or downgrade.",
|
||||
"body": "<h2>Risk severity updated</h2>\n<p>Risk profile <strong>{{payload.profile.id}}</strong> changed severity from {{payload.previous.severity}} to {{payload.current.severity}} at {{event.ts}}.</p>\n<ul>\n <li>Asset: {{payload.asset.purl}}</li>\n <li>Profile version: {{payload.profile.version}}</li>\n <li>Reason: {{payload.reason}}</li>\n</ul>\n<p>View details: <a href=\"{{payload.links.console}}\">Console</a></p>\n",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-24"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"schemaVersion": "notify.template@1",
|
||||
"templateId": "tmpl-risk-severity-change-slack-en-us",
|
||||
"tenantId": "bootstrap",
|
||||
"channelType": "slack",
|
||||
"key": "tmpl-risk-severity-change",
|
||||
"locale": "en-us",
|
||||
"renderMode": "markdown",
|
||||
"format": "json",
|
||||
"description": "Slack notice for risk severity escalation or downgrade.",
|
||||
"body": "*Risk severity changed* for {{payload.profile.id}}\n• from: {{payload.previous.severity}} → to: {{payload.current.severity}}\n• asset: {{payload.asset.purl}}\n• version: {{payload.profile.version}}\n• reason: {{payload.reason}}\n<{{payload.links.console}}|Open in console>",
|
||||
"metadata": {
|
||||
"author": "notifications-bootstrap",
|
||||
"version": "2025-11-24"
|
||||
}
|
||||
}
|
||||
56
devops/offline/fixtures/notifier/verify_notify_kit.sh
Normal file
56
devops/offline/fixtures/notifier/verify_notify_kit.sh
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd "$(dirname "$0")" && pwd)
|
||||
|
||||
missing=0
|
||||
for f in notify-kit.manifest.json notify-kit.manifest.dsse.json artifact-hashes.json; do
|
||||
if [ ! -f "$ROOT/$f" ]; then
|
||||
echo "[FAIL] missing $f" >&2
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$missing" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
python - <<'PY'
|
||||
import json, sys, pathlib, base64
|
||||
try:
|
||||
import blake3
|
||||
except ImportError:
|
||||
sys.stderr.write("blake3 module missing; install with `python -m pip install blake3`\n")
|
||||
sys.exit(1)
|
||||
|
||||
if '__file__' in globals() and __file__ not in (None, '<stdin>'):
|
||||
root = pathlib.Path(__file__).resolve().parent
|
||||
else:
|
||||
root = pathlib.Path.cwd()
|
||||
hashes = json.loads((root / "artifact-hashes.json").read_text())
|
||||
|
||||
def h(path: pathlib.Path):
|
||||
if path.suffix == ".json":
|
||||
data = json.dumps(json.loads(path.read_text()), sort_keys=True, separators=(',', ':')).encode()
|
||||
else:
|
||||
data = path.read_bytes()
|
||||
return blake3.blake3(data).hexdigest()
|
||||
|
||||
ok = True
|
||||
for entry in hashes["entries"]:
|
||||
path = root.parent.parent / entry["path"]
|
||||
digest = entry["digest"]
|
||||
if not path.exists():
|
||||
sys.stderr.write(f"[FAIL] missing file {path}\n")
|
||||
ok = False
|
||||
continue
|
||||
actual = h(path)
|
||||
if actual != digest:
|
||||
sys.stderr.write(f"[FAIL] digest mismatch {path}: expected {digest}, got {actual}\n")
|
||||
ok = False
|
||||
|
||||
if not ok:
|
||||
sys.exit(1)
|
||||
|
||||
print("[OK] All artifact hashes verified with blake3.")
|
||||
PY
|
||||
Reference in New Issue
Block a user