Implement ledger metrics for observability and add tests for Ruby packages endpoints
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Added `LedgerMetrics` class to record write latency and total events for ledger operations. - Created comprehensive tests for Ruby packages endpoints, covering scenarios for missing inventory, successful retrieval, and identifier handling. - Introduced `TestSurfaceSecretsScope` for managing environment variables during tests. - Developed `ProvenanceMongoExtensions` for attaching DSSE provenance and trust information to event documents. - Implemented `EventProvenanceWriter` and `EventWriter` classes for managing event provenance in MongoDB. - Established MongoDB indexes for efficient querying of events based on provenance and trust. - Added models and JSON parsing logic for DSSE provenance and trust information.
This commit is contained in:
@@ -19,7 +19,7 @@ Templates shape the payload rendered for each channel when a rule action fires.
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| `templateId` | string | Stable identifier (UUID/slug). |
|
||||
| `templateId` | string | Stable identifier (UUID/slug). |
|
||||
| `tenantId` | string | Must match the tenant header in API calls. |
|
||||
| `channelType` | [`NotifyChannelType`](../modules/notify/architecture.md#5-channels--connectors-plug-ins) | Determines connector payload envelope. |
|
||||
| `key` | string | Human-readable key referenced by rules (`tmpl-critical`). |
|
||||
@@ -109,22 +109,95 @@ When delivering via email, connectors automatically attach a plain-text alternat
|
||||
|
||||
---
|
||||
|
||||
## 5. Preview and validation
|
||||
|
||||
- `POST /channels/{id}/test` accepts an optional `templateId` and sample payload to produce a rendered preview without dispatching the event. Results include channel type, target, title/summary, locale, body hash, and connector metadata.
|
||||
- UI previews rely on the same API and highlight connector fallbacks (e.g., Teams adaptive card vs. text fallback).
|
||||
- Offline Kit scenarios can call `/internal/notify/templates/normalize` to ensure bundled templates match the canonical schema before packaging.
|
||||
|
||||
---
|
||||
|
||||
## 6. Best practices
|
||||
|
||||
- Keep channel-specific limits in mind (Slack block/character quotas, Teams adaptive card size, email line length). Lean on digests to summarise long lists.
|
||||
- Provide locale-specific versions for high-volume tenants; Notify selects the closest locale, falling back to `en-us`.
|
||||
- Store connector-specific hints (`metadata.layout`, `metadata.emoji`) in template metadata rather than rules when they affect rendering.
|
||||
- Version template bodies through metadata (e.g., `metadata.revision: "2025-10-28"`) so tenants can track changes over time.
|
||||
- Run test previews whenever introducing new helpers to confirm body hashes remain stable across environments.
|
||||
|
||||
---
|
||||
|
||||
> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
|
||||
## 5. Preview and validation
|
||||
|
||||
- `POST /channels/{id}/test` accepts an optional `templateId` and sample payload to produce a rendered preview without dispatching the event. Results include channel type, target, title/summary, locale, body hash, and connector metadata.
|
||||
- UI previews rely on the same API and highlight connector fallbacks (e.g., Teams adaptive card vs. text fallback).
|
||||
- Offline Kit scenarios can call `/internal/notify/templates/normalize` to ensure bundled templates match the canonical schema before packaging.
|
||||
|
||||
---
|
||||
|
||||
## 6. Best practices
|
||||
|
||||
- Keep channel-specific limits in mind (Slack block/character quotas, Teams adaptive card size, email line length). Lean on digests to summarise long lists.
|
||||
- Provide locale-specific versions for high-volume tenants; Notify selects the closest locale, falling back to `en-us`.
|
||||
- Store connector-specific hints (`metadata.layout`, `metadata.emoji`) in template metadata rather than rules when they affect rendering.
|
||||
- Version template bodies through metadata (e.g., `metadata.revision: "2025-10-28"`) so tenants can track changes over time.
|
||||
- Run test previews whenever introducing new helpers to confirm body hashes remain stable across environments.
|
||||
|
||||
---
|
||||
|
||||
## 7. Attestation & signing lifecycle templates (NOTIFY-ATTEST-74-001)
|
||||
|
||||
Attestation lifecycle events (verification failures, expiring attestations, key revocations, transparency anomalies) reuse the same structural context so operators can differentiate urgency while reusing channels. Every template **must** surface:
|
||||
|
||||
- **Subject** (`payload.subject.digest`, `payload.subject.repository`, `payload.subject.tag`).
|
||||
- **Attestation metadata** (`payload.attestation.kind`, `payload.attestation.id`, `payload.attestation.issuedAt`, `payload.attestation.expiresAt`).
|
||||
- **Signer/Key fingerprint** (`payload.signer.kid`, `payload.signer.algorithm`, `payload.signer.rotationId`).
|
||||
- **Traceability** (`payload.links.console`, `payload.links.rekor`, `payload.links.docs`).
|
||||
|
||||
### 7.1 Template keys & channels
|
||||
|
||||
| Event | Template key | Required channels | Optional channels | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Verification failure (`attestor.verification.failed`) | `tmpl-attest-verify-fail` | Slack `sec-alerts`, Email `supply-chain@`, Webhook (Pager/SOC) | Teams `risk-war-room`, Custom SIEM feed | Include failure code, Rekor UUID, last-known good attestation link. |
|
||||
| Expiring attestation (`attestor.attestation.expiring`) | `tmpl-attest-expiry-warning` | Email summary, Slack reminder | Digest window (daily) | Provide expiration window, renewal instructions, `expiresIn` helper. |
|
||||
| Key revocation/rotation (`authority.keys.revoked`, `authority.keys.rotated`) | `tmpl-attest-key-rotation` | Email + Webhook | Slack (if SOC watches channel) | Add rotation batch ID, impacted tenants/services, remediation steps. |
|
||||
| Transparency anomaly (`attestor.transparency.anomaly`) | `tmpl-attest-transparency-anomaly` | Slack high-priority, Webhook, PagerDuty | Email follow-up | Show Rekor index delta, witness ID, anomaly classification, recommended actions. |
|
||||
|
||||
Assign these keys when creating templates so rule actions can reference them deterministically (`actions[].template: "tmpl-attest-verify-fail"`).
|
||||
|
||||
### 7.2 Context helpers
|
||||
|
||||
- `attestation_status_badge status`: renders ✅/⚠️/❌ depending on verdict (`valid`, `expiring`, `failed`).
|
||||
- `expires_in expiresAt now`: returns human-readable duration, constrained to deterministic units (h/d).
|
||||
- `fingerprint key`: shortens long key IDs/pems, exposing the last 10 characters.
|
||||
|
||||
### 7.3 Slack sample (verification failure)
|
||||
|
||||
```hbs
|
||||
:rotating_light: {{attestation_status_badge payload.failure.status}} verification failed for `{{payload.subject.digest}}`
|
||||
Signer: `{{fingerprint payload.signer.kid}}` ({{payload.signer.algorithm}})
|
||||
Reason: `{{payload.failure.reasonCode}}` — {{payload.failure.reason}}
|
||||
Last valid attestation: {{link "Console report" payload.links.console}}
|
||||
Rekor entry: {{link "Transparency log" payload.links.rekor}}
|
||||
```
|
||||
|
||||
### 7.4 Email sample (expiring attestation)
|
||||
|
||||
```hbs
|
||||
<h2>Attestation expiry notice</h2>
|
||||
<p>The attestation for <code>{{payload.subject.repository}}</code> (digest {{payload.subject.digest}}) expires on <strong>{{payload.attestation.expiresAt}}</strong>.</p>
|
||||
<ul>
|
||||
<li>Issued: {{payload.attestation.issuedAt}}</li>
|
||||
<li>Signer: {{payload.signer.kid}} ({{payload.signer.algorithm}})</li>
|
||||
<li>Time remaining: {{expires_in payload.attestation.expiresAt event.ts}}</li>
|
||||
</ul>
|
||||
<p>Please rotate the attestation before expiry. Reference <a href="{{payload.links.docs}}">renewal steps</a>.</p>
|
||||
```
|
||||
|
||||
### 7.5 Webhook sample (transparency anomaly)
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "attestor.transparency.anomaly",
|
||||
"tenantId": "{{event.tenant}}",
|
||||
"subjectDigest": "{{payload.subject.digest}}",
|
||||
"rekorIndex": "{{payload.transparency.rekorIndex}}",
|
||||
"witnessId": "{{payload.transparency.witnessId}}",
|
||||
"anomaly": "{{payload.transparency.classification}}",
|
||||
"detailsUrl": "{{payload.links.console}}",
|
||||
"recommendation": "{{payload.recommendation}}"
|
||||
}
|
||||
```
|
||||
|
||||
### 7.6 Offline kit guidance
|
||||
|
||||
- Bundle these templates (JSON export) under `offline/notifier/templates/attestation/`.
|
||||
- Baseline English templates for Slack, Email, and Webhook ship in the repository at `offline/notifier/templates/attestation/*.template.json`; copy and localise them per tenant as needed.
|
||||
- Provide localized variants for `en-us` and `de-de` at minimum; additional locales can be appended per customer.
|
||||
- Include preview fixtures in Offline Kit smoke tests to guarantee channel render parity when air-gapped.
|
||||
|
||||
---
|
||||
|
||||
> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
|
||||
|
||||
Reference in New Issue
Block a user