docs: convert remaining ASCII diagrams to mermaid (audit closure)

Audit pass over docs/ found 4 files with non-mermaid (ASCII
box-drawing) diagrams in fenced code blocks. The other 9 doc files
already used mermaid blocks (architecture.md, demo-advanced.md,
ci-pipeline.md, concepts.md, est.md, legacy-est-scep.md, mcp.md,
qa-test-guide.md, scep-intune.md). Rendering parity for everything
in docs/.

Conversions:

  approval-workflow.md
    1 ASCII swimlane → sequenceDiagram with named participants
    (Operator A / CertificateService / Job+ApprovalRequest /
    Operator B / ApprovalService / Scheduler). Same content: the
    same-actor RBAC reject path, the AwaitingApproval gate, the
    audit + Prometheus side effects.

  intermediate-ca-hierarchy.md
    1 lifecycle ASCII → stateDiagram-v2 (created → active → retiring
    → retired with the drain-first refusal annotation).
    3 ASCII tree patterns → 3 flowchart TD diagrams (FedRAMP 4-level
    boundary CA, financial-services 3-level policy CA, internal-PKI
    2-level). Same depth, same path_len + permitted-DNS labels.

  runbook-cloud-targets.md
    1 dual-column ASCII flow → flowchart TD with two subgraphs
    (AWS ACM path, Azure Key Vault path) joining at the audit +
    Prometheus exposer node. Same 6-step deploy sequence on each
    side with the rollback-on-mismatch step explicit.

  runbook-expiry-alerts.md
    1 nested-loop ASCII flow → flowchart TD with three nested
    subgraphs (per-cert main loop / per-threshold inner / per-channel
    fault-isolating dispatch). Same dedup + Prometheus + audit-row
    side effects per channel.

Verified locally:
  Audit re-run: every fenced block in docs/*.md that does NOT open
    with ```mermaid contains zero ASCII box-drawing characters
    (┌ └ │ ─ ━ ═ ║ ╔ ╚ ▼ ▲).
  Mermaid block tally: 39 across 13 files (up from 32 across 9
    files pre-audit). The +7 new blocks are the 4 conversions plus
    the lifecycle + 3 tree patterns expanded out of the single
    intermediate-ca-hierarchy.md ASCII section.

No code or test changes. Doc-only commit.
This commit is contained in:
shankar0123
2026-05-04 02:40:01 +00:00
parent 478c75dffe
commit 57ae1184b1
4 changed files with 108 additions and 127 deletions
+19 -36
View File
@@ -6,42 +6,25 @@ Closes the procurement-checklist question "How do you enforce two-person integri
## End-to-end flow
```
Operator A (or scheduler) Operator B
│ │
▼ │
POST /api/v1/certificates/ │
{id}/renew │
(or renewal-loop tick) │
│ │
▼ │
CertificateService.TriggerRenewal │
├── reads profile.RequiresApproval │
├── creates Job at │
│ JobStatusAwaitingApproval │
└── creates parallel │
ApprovalRequest row │
(state=pending, │
requested_by=Operator A) │
│ │
│ scheduler skips — │
│ AwaitingApproval is │
│ NOT a dispatchable status │
│ │
│ GET /api/v1/approvals?state=pending
│ ▼
│ POST /api/v1/approvals/{id}/approve
│ │
▼ ▼
ApprovalService.Approve(decided_by=Operator B, note=...)
├── RBAC: rejects if Operator B == Operator A → ErrApproveBySameActor (HTTP 403)
├── transitions ApprovalRequest to state=approved
├── transitions Job from AwaitingApproval → Pending
├── records audit row (action=approval_approved, actor=Operator B)
└── increments certctl_approval_decisions_total{outcome=approved,profile_id=...}
Scheduler picks up Job at Pending, dispatches to issuer connector — cert issues normally.
```mermaid
sequenceDiagram
autonumber
participant A as Operator A<br/>(or scheduler)
participant SVC as CertificateService<br/>.TriggerRenewal
participant JOB as Job + ApprovalRequest
participant B as Operator B
participant APR as ApprovalService.Approve
participant SCH as Scheduler
A->>SVC: POST /api/v1/certificates/{id}/renew<br/>(or renewal-loop tick)
SVC->>JOB: read profile.RequiresApproval;<br/>create Job @ JobStatusAwaitingApproval;<br/>create ApprovalRequest<br/>(state=pending, requested_by=Operator A)
Note over JOB,SCH: Scheduler skips —<br/>AwaitingApproval is NOT a dispatchable status
B->>JOB: GET /api/v1/approvals?state=pending
B->>APR: POST /api/v1/approvals/{id}/approve<br/>(decided_by=Operator B, note=...)
APR->>APR: RBAC: reject if Operator B == Operator A<br/>→ ErrApproveBySameActor (HTTP 403)
APR->>JOB: ApprovalRequest → state=approved;<br/>Job AwaitingApproval → Pending;<br/>audit row (action=approval_approved,<br/>actor=Operator B);<br/>certctl_approval_decisions_total<br/>{outcome=approved,profile_id=...}++
SCH->>JOB: pick up Pending → dispatch to issuer connector
JOB-->>A: cert issues normally
```
## Configuration