# MVG Org Signing Service — Strict Intake Template (v23.5)

This template tightens the org signing flow to match typical enterprise security intake expectations:
**idempotency**, **replay protection**, **auditability**, and **policy-driven key alias selection**.

This does **not** ship private keys in the website. Production deployments must use org-controlled KMS/HSM.

---

## Goals

- **Private key 0 shipped**: website distributes only public keys and signed artifacts.
- **DSSEv1 PAE**: all signatures are over DSSE PAE(payloadType, payloadBytes).
- **Idempotent signing**: repeated requests return the same response iff request hash matches.
- **Replay protection**: nonce + TTL window prevents replays.
- **Audit trail**: minimal audit fields in request/response; DSSE ext contains a digest and references.
- **KMS key alias policy**: request selects a key alias, service enforces allowlist.

---

## Strict endpoint

`POST /v1/sign-report-strict`

### Required header
- `Idempotency-Key: <string 8..128>`

### Request schema (JSON)
`schema_id = "mvg.org_signer.signing_request@1"`

Required fields:
- `request_id` (UUID)
- `issued_utc`, `expires_utc` (RFC3339, max TTL 10 minutes recommended)
- `client_nonce_b64u` (base64url 16–64 random bytes)
- `payloadType` (string)
- `payload_b64u` (base64url payload bytes)
- `payload_sha256` (hex sha256(payload bytes))
- `kms.provider` ∈ `local | aws-kms | azure-keyvault`
- `kms.key_alias` (allowlisted by policy)
- `audit.requester`, `audit.ticket` (strings)

### Server validation (MUST)
- Reject if payload_sha256 mismatch.
- Reject if nonce has been seen within TTL.
- Reject if expires_utc <= issued_utc or TTL > policy max.
- Reject if key_alias not allowlisted (403).
- Idempotency:
  - Same Idempotency-Key + same request_hash → return cached response
  - Same Idempotency-Key + different request_hash → 409 Conflict

### Response schema
`schema_id = "mvg.org_signer.signing_response@1"`

- `audit_receipt.server_utc` = `2026-02-09T02:11:10Z`
- `audit_receipt.request_hash_sha256` = sha256(canonical(request subset))
- `audit_receipt.signing_kid` = keyid used to sign DSSE
- `signed_report_dsse` = DSSE envelope (payload = report bytes, sig = Ed25519 over DSSE PAE)

---

## KMS key alias policy (recommended)

- Use stable aliases, never raw key IDs in client flows:
  - AWS: `alias/mvg-report-signer`
  - Azure: `kv://<vault>/<key-name>`
- Service MUST enforce allowlist via config (`--allow-alias` or env).

---

## Files shipped with the website (public-safe)

- `/downloads/specs/MVG_OrgSigner_OpenAPI_v23_5.yaml`
- `/downloads/specs/MVG_OrgSigner_curl_examples_v23_5.md`
- `/downloads/MVG_OrgSigner_MockServer_v23_5.zip`

The mock server includes backend slots (local/aws-kms/azure-keyvault) to show where real KMS/HSM
integration would be attached.

---

## OpenAPI

See `/downloads/specs/MVG_OrgSigner_OpenAPI_v23_5.yaml`
