SDS-031: Authority & Ownership Boundaries

Type

Software Design Specification - Governance Protocol

Status

Draft

Purpose

Defines the Authority Boundaries for SEA-Forge™, the Internal Federated Ledger (IFL), and the Semantic Core. This specification establishes:

This spec is the authoritative source for “who can do what” across the SEA™ ecosystem.


1. Role Definitions (RBAC Model)

1.1. Role Catalog

Role ID Role Name Scope Description
R-DS Domain Steward Bounded Context Semantic owner of a domain’s concepts, policies, and business rules.
R-AG Architecture Governor System-wide CALM/architecture compliance owner. Approves structural changes.
R-LC Ledger Custodian IFL Cluster IFL operator, key custodian, node manager.
R-SO Security Officer System-wide Approves break-glass actions, key rotation, security exceptions.
R-RM Release Manager Deployment Pipeline Deployment authority, controls promotion gates.
R-DEV Developer Feature/PR scope Proposal author, implements changes. Cannot self-approve in production.
R-AA Automated Agent Task scope Recommends actions, executes approved automation. Cannot approve.

1.2. Role Hierarchy & Inheritance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌─────────────────────────────────────────────────────────────────┐
│                    GOVERNANCE AUTHORITY                         │
├─────────────────────────────────────────────────────────────────┤
│  Security Officer (R-SO)                                        │
│    ├── Can delegate: Break-glass review (to R-AG)               │
│    └── Cannot delegate: Key rotation approval                   │
├─────────────────────────────────────────────────────────────────┤
│  Architecture Governor (R-AG)                                   │
│    ├── Can delegate: Semantic review (to R-DS)                  │
│    └── Cannot delegate: CALM compliance decisions               │
├─────────────────────────────────────────────────────────────────┤
│  Domain Steward (R-DS)                                          │
│    ├── Can delegate: Policy drafting (to R-DEV)                 │
│    └── Cannot delegate: Semantic meaning decisions              │
├─────────────────────────────────────────────────────────────────┤
│  Ledger Custodian (R-LC)                                        │
│    ├── Can delegate: Operational monitoring (to R-AA)           │
│    └── Cannot delegate: Key custody, node admission             │
├─────────────────────────────────────────────────────────────────┤
│  Release Manager (R-RM)                                         │
│    ├── Can delegate: Staging deployment (to R-AA)               │
│    └── Cannot delegate: Production promotion                    │
└─────────────────────────────────────────────────────────────────┘

1.3. Role Assignment Constraints

Constraint ID Rule Rationale
C-01 A single person MUST NOT hold both R-DS and R-AG for the same bounded context Prevents semantic-structural conflict of interest
C-02 R-LC MUST NOT also be R-SO Separation of operational and security authority
C-03 R-DEV cannot approve their own proposals in production environment Four-eyes principle
C-04 R-AA MUST have an R-* sponsor for any privileged action Traceability to human accountability

2. RACI Matrix

Legend: R = Responsible, A = Accountable, C = Consulted, I = Informed

2.1. Semantic Governance Decisions

Decision R-DS R-AG R-LC R-SO R-RM R-DEV R-AA
Propose Semantic Change R C I I I R R
Approve Semantic Change (Non-Breaking) A C I I I - -
Approve Semantic Change (Breaking) R A I C C - -
Accept Semantic Debt A C I C I R -
Resolve Semantic Debt A I I I I R R
Invoke Break-glass R C I A C R -

2.2. Identity & Ledger Decisions

Decision R-DS R-AG R-LC R-SO R-RM R-DEV R-AA
Mint Identity Token I C R I A I R
Rotate Signing Key I I R A I - -
Add/Remove IFL Node I C R A I - -
Revoke Compromised Key I I R A I - -

2.3. Schema & Pipeline Decisions

Decision R-DS R-AG R-LC R-SO R-RM R-DEV R-AA
Approve Schema Evolution (Minor) A C I I I R -
Approve Schema Evolution (Major) C A I C C R -
Change Canonical Normalizer Algorithm C A I C I R -
Promote to Production I C I I A I R
Emergency Rollback C C R A R I R

3. Separation of Duties (SoD) Rules

3.1. Mandatory Separations

SoD ID Actor 1 Actor 2 Transaction Enforcement
SOD-01 Proposer Approver SemanticChangeProposal (production) CI Gate blocks if proposer == approver
SOD-02 Debt Requester Debt Acceptor SemanticDebt.accept Ledger rejects if same principal
SOD-03 Break-glass Requester Break-glass Approver BreakGlass.activate Security Officer MUST be different from requester
SOD-04 Key Generator Key Approver KeyRotation.execute Two-party control for production keys
SOD-05 Minter Semantic Owner Mint.execute for governance entities Domain Steward cannot mint their own definitions

3.2. Enforcement Mechanism

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Policy: SoD Enforcement (evaluated at transaction commit)
Policy SeparationOfDutiesEnforcement:
  applies_to: [SemanticChangeProposal, SemanticDebtAcceptance, BreakGlassActivation, MintTransaction, KeyRotation]

  rule EnforceTwoPartyControl:
    when:
      - environment == "production"
      - action.requires_approval == true
    then:
      - REQUIRE action.approver != action.proposer
      - REQUIRE action.approver.role IN [R-DS, R-AG, R-SO, R-RM]  # Excludes R-DEV, R-AA
      - EMIT AuditEvent(type: "sod.enforced", actors: [action.proposer, action.approver])
    else:
      - REJECT with "SoD Violation: Self-approval not permitted in production"

4. Decision Protocols

4.1. SemanticChangeProposal Lifecycle

Complete Workflow: For the full SemanticChangeProposal schema, option generation policy, impact analysis algorithm, and anti-rubber-stamp guardrails, see §5. Decision Execution below.

States: draftsubmittedunder_reviewapproved rejectedenacted withdrawn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────┐    submit()    ┌───────────┐   assign_reviewer()   ┌──────────────┐
│  draft  │ ─────────────► │ submitted │ ────────────────────► │ under_review │
└─────────┘                └───────────┘                       └──────────────┘
     │                           │                                    │
     │ withdraw()                │ withdraw()                         │
     ▼                           ▼                                    │
┌───────────┐              ┌───────────┐                              │
│ withdrawn │              │ withdrawn │                              │
└───────────┘              └───────────┘                              │
                                                        ┌─────────────┴─────────────┐
                                                        │                           │
                                                   approve()                   reject()
                                                        │                           │
                                                        ▼                           ▼
                                                  ┌──────────┐               ┌──────────┐
                                                  │ approved │               │ rejected │
                                                  └──────────┘               └──────────┘
                                                        │
                                                   enact()
                                                        │
                                                        ▼
                                                  ┌─────────┐
                                                  │ enacted │
                                                  └─────────┘

Protocol Fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  "proposalId": "ifl:hash:<sha256>",
  "type": "semantic_change",
  "scope": {
    "boundedContext": "string",
    "affectedConcepts": ["ConceptId"],
    "breakingChange": "boolean"
  },
  "author": {
    "principalId": "string",
    "role": "R-DEV | R-DS"
  },
  "reviewers": [
    {
      "principalId": "string",
      "role": "R-DS | R-AG",
      "assignedAt": "ISO8601"
    }
  ],
  "state": "draft | submitted | under_review | approved | rejected | enacted | withdrawn",
  "stateHistory": [
    {
      "from": "string",
      "to": "string",
      "actor": "principalId",
      "timestamp": "ISO8601",
      "rationale": "string"
    }
  ],
  "createdAt": "ISO8601",
  "updatedAt": "ISO8601"
}

Invariants:

Approval Expiry & Version Binding:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "approval": {
    "approvalId": "uuid",
    "proposalId": "ifl:hash:<sha256>",
    "proposalVersion": "v2.3.1",
    "approver": {
      "principalId": "string",
      "role": "R-DS | R-AG",
      "capabilityToken": "jwt-token"
    },
    "approvedAt": "ISO8601",
    "expiresAt": "ISO8601",
    "boundTo": {
      "commitSha": "string",
      "artifactHash": "sha256:...",
      "boundAt": "ISO8601"
    },
    "signature": {
      "algorithm": "Ed25519",
      "publicKey": "hex",
      "value": "hex"
    }
  }
}

Expiry Rules: | Proposal Type | Environment | Default TTL | Maximum TTL | |—————|————-|————-|————-| | Non-breaking change | staging | 7 days | 14 days | | Non-breaking change | production | 24 hours | 7 days | | Breaking change | staging | 24 hours | 7 days | | Breaking change | production | 4 hours | 24 hours |

Binding Invariants:

4.2. SemanticDebt Acceptance Protocol

States: openaccepted rejectedmitigatingresolved expired

Acceptance Constraints: | Field | Requirement | |——-|————-| | acceptor | MUST be R-DS or R-AG (not R-DEV, not R-AA) | | expiration | MANDATORY. Maximum 90 days for High severity, 30 days for Critical | | mitigationPlan | MANDATORY for High and Critical severity | | reviewCadence | MANDATORY. Defines revalidation schedule (default: 14 days) |

Protocol Fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "debtId": "ifl:hash:<sha256>",
  "status": "open | accepted | rejected | mitigating | resolved | expired",
  "severity": "low | medium | high | critical",
  "acceptedBy": {
    "principalId": "string",
    "role": "R-DS | R-AG",
    "timestamp": "ISO8601"
  },
  "expiration": "ISO8601",
  "reviewCadence": "P14D", // ISO8601 Duration
  "nextReviewDate": "ISO8601",
  "mitigationPlan": {
    "summary": "string",
    "milestones": [{ "description": "string", "dueDate": "ISO8601" }]
  },
  "acceptanceRationale": "string"
}

Invariants:

4.3. Break-glass Protocol

Purpose: Emergency override of standard governance controls when business continuity requires immediate action.

States: requestedapproved deniedactiveexpired revoked

Protocol Fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  "breakGlassId": "uuid",
  "requestedBy": {
    "principalId": "string",
    "role": "R-DS | R-RM | R-DEV",
    "timestamp": "ISO8601"
  },
  "approvedBy": {
    "principalId": "string",
    "role": "R-SO", // MUST be Security Officer
    "timestamp": "ISO8601"
  },
  "scope": {
    "bypassedControls": ["control_id"],
    "affectedArtifacts": ["artifact_id"],
    "boundedContexts": ["context_id"]
  },
  "reason": {
    "category": "production_outage | security_incident | regulatory_deadline | data_corruption",
    "description": "string",
    "ticketReference": "string" // Link to incident ticket
  },
  "constraints": {
    "maxDuration": "PT4H", // ISO8601 Duration, Maximum 4 hours default
    "expiresAt": "ISO8601",
    "renewalLimit": 2,
    "renewalCount": 0
  },
  "status": "requested | approved | denied | active | expired | revoked",
  "auditTrail": [
    {
      "action": "string",
      "actor": "principalId",
      "timestamp": "ISO8601",
      "details": "object"
    }
  ]
}

Invariants:

Audit Event (emitted on every state transition):

1
2
3
4
5
6
7
8
{
  "type": "governance.authority.break-glass-state-changed",
  "breakGlassId": "uuid",
  "from": "requested",
  "to": "approved",
  "actor": "principalId",
  "timestamp": "ISO8601"
}

4.4. Attestation Protocol (Identity Tokens)

Purpose: Controls the transition from pre-mint (ifl:hash) to attested (ifl:token) identity.

States: pending_validationvalidatedpending_signaturesignedcommitted

Protocol Fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  "attestRequestId": "uuid",
  "sourceHash": "ifl:hash:<sha256>",
  "targetArtifact": {
    "type": "Concept | Policy | Entity | Resource | Flow",
    "namespace": "string",
    "name": "string"
  },
  "validationResult": {
    "schemaValid": "boolean",
    "semanticValid": "boolean",
    "driftCheckPassed": "boolean",
    "validatedAt": "ISO8601",
    "validator": "R-AA | R-DEV"
  },
  "signature": {
    "algorithm": "Ed25519",
    "publicKey": "hex",
    "signatureValue": "hex",
    "signedAt": "ISO8601",
    "signedBy": {
      "principalId": "string",
      "role": "R-RM | R-LC" // Release Manager or Ledger Custodian
    }
  },
  "bindingRecord": {
    "targetToken": "ifl:token:<chain>:<contract>:<tokenId>",
    "committedAt": "ISO8601",
    "ledgerEntryId": "string"
  },
  "status": "pending_validation | validated | pending_signature | signed | committed | failed"
}

Invariants:


5. Decision Execution

This chapter defines the complete Semantic Change Proposal Workflow that implements the forced-choice governance mechanism required by PRD-018. The workflow provides the technical enforcement of the authority roles defined in §1-4.

5.1. SemanticChangeProposal Schema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://schemas.newsea.io/governance/semantic-change-proposal/v1.schema.json",
  "title": "SemanticChangeProposal",
  "description": "A structured proposal for changing canonical semantics with forced-choice options.",
  "type": "object",
  "required": [
    "proposalId",
    "version",
    "status",
    "changeType",
    "author",
    "affectedArtifacts",
    "options",
    "createdAt"
  ],
  "properties": {
    "proposalId": {
      "type": "string",
      "pattern": "^ifl:hash:[a-f0-9]{64}$",
      "description": "Deterministic hash of proposal canonical form"
    },
    "version": {
      "type": "string",
      "pattern": "^v\\d+\\.\\d+\\.\\d+$",
      "description": "Semantic version of the proposal"
    },
    "status": {
      "type": "string",
      "enum": [
        "draft",
        "options_generated",
        "under_review",
        "approved",
        "rejected",
        "enacted",
        "withdrawn"
      ],
      "description": "Current lifecycle state"
    },
    "changeType": {
      "type": "string",
      "enum": [
        "concept_definition",
        "policy_update",
        "normalizer_rule",
        "identity_schema",
        "resource_definition",
        "flow_definition"
      ],
      "description": "Category of semantic change"
    },
    "breakingChange": {
      "type": "boolean",
      "description": "True if change breaks backward compatibility"
    },
    "author": {
      "$ref": "#/definitions/Principal"
    },
    "affectedArtifacts": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/ArtifactReference"
      },
      "minItems": 1
    },
    "options": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/ChangeOption"
      },
      "minItems": 1,
      "maxItems": 3,
      "description": "Generated options with trade-offs"
    },
    "selectedOption": {
      "$ref": "#/definitions/OptionSelection",
      "description": "The option chosen by the approver (null until approved)"
    },
    "reviewers": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/ReviewerAssignment"
      }
    },
    "stateHistory": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/StateTransition"
      }
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time"
    }
  },
  "definitions": {
    "Principal": {
      "type": "object",
      "required": ["principalId", "role"],
      "properties": {
        "principalId": { "type": "string" },
        "role": {
          "type": "string",
          "enum": ["R-DS", "R-AG", "R-LC", "R-SO", "R-RM", "R-DEV", "R-AA"]
        }
      }
    },
    "ArtifactReference": {
      "type": "object",
      "required": ["artifactId", "artifactType", "namespace"],
      "properties": {
        "artifactId": { "type": "string" },
        "artifactType": {
          "type": "string",
          "enum": [
            "Concept",
            "Policy",
            "Entity",
            "Resource",
            "Flow",
            "NormalizerRule",
            "IdentitySchema"
          ]
        },
        "namespace": { "type": "string" },
        "currentVersion": { "type": "string" }
      }
    },
    "ChangeOption": {
      "type": "object",
      "required": [
        "optionId",
        "category",
        "summary",
        "impactAnalysis",
        "riskRating",
        "requiredApproverRoles",
        "invariantsPreserved",
        "invariantsViolated"
      ],
      "properties": {
        "optionId": {
          "type": "string",
          "pattern": "^opt-(conservative|balanced|aggressive)$"
        },
        "category": {
          "type": "string",
          "enum": ["conservative", "balanced", "aggressive"]
        },
        "summary": {
          "type": "string",
          "minLength": 50,
          "description": "Human-readable summary of this option"
        },
        "detailedDescription": {
          "type": "string",
          "description": "Extended explanation of the option"
        },
        "impactAnalysis": {
          "$ref": "#/definitions/ImpactAnalysis"
        },
        "riskRating": {
          "type": "string",
          "enum": ["low", "medium", "high", "critical"]
        },
        "requiredApproverRoles": {
          "type": "array",
          "items": { "type": "string", "enum": ["R-DS", "R-AG", "R-SO"] },
          "minItems": 1
        },
        "invariantsPreserved": {
          "type": "array",
          "items": { "type": "string" },
          "description": "List of invariant IDs that remain intact"
        },
        "invariantsViolated": {
          "type": "array",
          "items": { "type": "string" },
          "description": "List of invariant IDs that would be violated"
        },
        "tradeOffExplanation": {
          "type": "string",
          "description": "Explicit explanation of what is gained and lost"
        },
        "recommendedFor": {
          "type": "string",
          "description": "Scenario where this option is most appropriate"
        }
      }
    },
    "ImpactAnalysis": {
      "type": "object",
      "required": [
        "debtCreated",
        "debtRetired",
        "projectionsAffected",
        "compatibility",
        "blastRadius"
      ],
      "properties": {
        "debtCreated": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "debtType": { "type": "string" },
              "severity": {
                "type": "string",
                "enum": ["low", "medium", "high", "critical"]
              },
              "description": { "type": "string" }
            }
          }
        },
        "debtRetired": {
          "type": "array",
          "items": { "type": "string" },
          "description": "IDs of SemanticDebtItems resolved by this option"
        },
        "projectionsAffected": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "projectionTarget": { "type": "string" },
              "regenerationRequired": { "type": "boolean" },
              "estimatedEffort": { "type": "string" }
            }
          }
        },
        "compatibility": {
          "type": "object",
          "properties": {
            "backward": { "type": "boolean" },
            "forward": { "type": "boolean" },
            "migrationPath": { "type": "string" }
          }
        },
        "blastRadius": {
          "type": "object",
          "properties": {
            "conceptsAffected": { "type": "integer", "minimum": 0 },
            "policiesAffected": { "type": "integer", "minimum": 0 },
            "consumersAffected": { "type": "integer", "minimum": 0 },
            "servicesAffected": {
              "type": "array",
              "items": { "type": "string" }
            }
          }
        }
      }
    },
    "OptionSelection": {
      "type": "object",
      "required": [
        "selectedOptionId",
        "selectedBy",
        "justification",
        "selectedAt",
        "signature"
      ],
      "properties": {
        "selectedOptionId": {
          "type": "string",
          "pattern": "^opt-(conservative|balanced|aggressive)$"
        },
        "selectedBy": {
          "$ref": "#/definitions/Principal"
        },
        "justification": {
          "type": "string",
          "minLength": 20,
          "description": "Required explanation for why this option was chosen"
        },
        "alternativesConsidered": {
          "type": "string",
          "description": "Optional: why other options were rejected"
        },
        "selectedAt": {
          "type": "string",
          "format": "date-time"
        },
        "expiresAt": {
          "type": "string",
          "format": "date-time"
        },
        "signature": {
          "$ref": "#/definitions/Signature"
        }
      }
    },
    "Signature": {
      "type": "object",
      "required": ["algorithm", "publicKey", "value"],
      "properties": {
        "algorithm": { "type": "string", "const": "Ed25519" },
        "publicKey": { "type": "string" },
        "value": { "type": "string" }
      }
    },
    "ReviewerAssignment": {
      "type": "object",
      "required": ["principalId", "role", "assignedAt"],
      "properties": {
        "principalId": { "type": "string" },
        "role": { "type": "string" },
        "assignedAt": { "type": "string", "format": "date-time" },
        "reviewedAt": { "type": "string", "format": "date-time" }
      }
    },
    "StateTransition": {
      "type": "object",
      "required": ["from", "to", "actor", "timestamp"],
      "properties": {
        "from": { "type": "string" },
        "to": { "type": "string" },
        "actor": { "type": "string" },
        "timestamp": { "type": "string", "format": "date-time" },
        "reason": { "type": "string" }
      }
    }
  }
}

5.2. Option Generation Policy

5.2.1. When to Generate Options

Change Type Min Options Max Options Policy
Concept Definition (new) 1 2 Conservative (minimal scope) + Balanced (full scope)
Concept Definition (modify) 2 3 Conservative + Balanced + Aggressive (if breaking change possible)
Policy Update 2 3 Always generate trade-offs for enforcement level
Normalizer Rule 1 3 Single option if purely additive; 3 if affects existing hashes
Identity Schema 2 3 Always 2+ due to migration implications
Resource/Flow Definition 1 3 Based on coupling analysis

5.2.2. Option Category Definitions

Conservative Option (opt-conservative):

Balanced Option (opt-balanced):

Aggressive Option (opt-aggressive):

5.2.3. Option Generation Algorithm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def generate_options(change_request: ChangeRequest) -> List[ChangeOption]:
    """Generates 1-3 options based on change characteristics."""
    options = []

    # Step 1: Always generate Conservative option
    conservative = generate_conservative_option(change_request)
    options.append(conservative)

    # Step 2: Generate Balanced option if change has meaningful scope
    if change_has_meaningful_scope(change_request):
        balanced = generate_balanced_option(change_request)
        options.append(balanced)

    # Step 3: Generate Aggressive option if breaking change is feasible
    if breaking_change_feasible(change_request):
        aggressive = generate_aggressive_option(change_request)
        options.append(aggressive)

    # Step 4: Ensure we have at least 1, at most 3
    assert 1 <= len(options) <= 3

    # Step 5: Compute impact analysis for each
    for option in options:
        option.impactAnalysis = compute_impact_analysis(change_request, option)
        option.riskRating = compute_risk_rating(option)
        option.requiredApproverRoles = determine_required_approvers(option)

    return options

5.3. Event Envelopes

Event Type Trigger Required Fields
sea.proposal.created Proposal enters draft proposalId, author, changeType, affectedArtifacts, timestamp
sea.proposal.options_generated Options generated proposalId, optionCount, optionSummaries, timestamp
sea.proposal.reviewer_assigned Reviewer assigned proposalId, reviewer, requiredRole, timestamp
sea.proposal.option_selected Approver selects option proposalId, selectedOptionId, approver, justification, signature, timestamp
sea.proposal.approved Proposal approved proposalId, selectedOptionId, approver, expiresAt, signature, timestamp
sea.proposal.rejected Proposal rejected proposalId, rejector, reason, timestamp
sea.proposal.enacted Change applied to IFL proposalId, ledgerEntryId, enactor, timestamp
sea.proposal.withdrawn Proposal withdrawn proposalId, withdrawer, reason, timestamp

Option Selection Event Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
  "specversion": "1.0",
  "id": "evt-uuid-12345",
  "type": "sea.proposal.option_selected",
  "source": "//governance/proposal-service",
  "time": "2025-12-22T10:30:00Z",
  "datacontenttype": "application/json",
  "data": {
    "proposalId": "ifl:hash:abc123...",
    "proposalVersion": "v1.0.0",
    "selectedOptionId": "opt-balanced",
    "optionCategory": "balanced",
    "approver": {
      "principalId": "principal:human:github:architect01",
      "role": "R-AG"
    },
    "justification": "Balanced option provides the capability we need while maintaining acceptable blast radius.",
    "signature": {
      "algorithm": "Ed25519",
      "publicKey": "0x1234abcd...",
      "value": "0xsig..."
    },
    "expiresAt": "2025-12-23T10:30:00Z"
  }
}

5.4. Anti-Rubber-Stamp Guardrails

Guardrail ID Rule Enforcement
GR-01 System cannot auto-select an option Option selection requires human click + signature
GR-02 Justification minimum length justification.length >= 20 characters
GR-03 Justification cannot be boilerplate ML classifier rejects “looks good”, “approved”, “LGTM”
GR-04 Four-eyes rule proposer != approver for production
GR-05 Option comparison required UI must display all options before selection enabled
GR-06 Risk acknowledgment for High/Critical Explicit checkbox: “I understand this option violates invariants: [list]”
GR-07 Time-bound review Proposals expire after 7 days without review
GR-08 No retroactive approval Options cannot be selected after proposal enacted

Boilerplate Detection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
BOILERPLATE_PATTERNS = [
    r"^(lgtm|looks good|approved|ok|fine|ship it)\.?$",
    r"^(no comments?|no issues?)\.?$",
    r"^(accept(ed)?|confirm(ed)?)\.?$",
    r"^(rubber stamp(ed)?|auto[- ]?approv(e|ed))\.?$"
]

def validate_justification(justification: str) -> ValidationResult:
    """Validates that justification is meaningful, not boilerplate."""
    normalized = justification.strip().lower()

    if len(justification) < 20:
        return ValidationResult.REJECT(
            "Justification too short. Please explain your decision rationale (min 20 chars)."
        )

    for pattern in BOILERPLATE_PATTERNS:
        if re.match(pattern, normalized, re.IGNORECASE):
            return ValidationResult.REJECT(
                "Justification appears to be boilerplate. Please provide specific reasoning."
            )

    return ValidationResult.PASS

Risk Acknowledgment (for High/Critical options):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "riskAcknowledgment": {
    "acknowledgedAt": "2025-12-22T10:35:00Z",
    "acknowledgedBy": "principal:human:github:architect01",
    "invariantsAcknowledged": [
      "I-COMPAT-01: Backward compatibility with v1 consumers",
      "I-SCHEMA-03: Canonical hash stability"
    ],
    "mitigationPlan": "Consumer migration scheduled for Q1; hash migration script prepared",
    "signature": {
      "algorithm": "Ed25519",
      "publicKey": "0x1234abcd...",
      "value": "0xsig..."
    }
  }
}

5.5. CLI Commands

Command Description
sea-proposal create --change-type <type> --artifact <path> --out <file> Create new proposal from change manifest
sea-proposal generate-options --proposal <file> --out <file> Generate options for a proposal
sea-proposal review --proposal <file> --approver <principal> Open interactive review UI
sea-proposal approve --proposal <file> --option <id> --justification <text> --signing-key <path> Approve by selecting an option
sea-proposal query --status <status> --since <date> --format json Query proposal history

6. Non-Delegable Decisions

The following decisions MUST be made by humans. Automated Agents (R-AA) may recommend but CANNOT approve or execute these actions.

Decision Category Specific Actions Required Role Automation Limit
Semantic Meaning Define business term meaning R-DS Recommend only
Semantic Meaning Resolve conflicting interpretations R-DS + R-AG Recommend only
Regulatory Interpretation Accept compliance exception R-SO Cannot participate
Ethical Trade-offs Approve conflicting values R-DS + R-SO Cannot participate
Key Custody Approve key rotation R-SO Cannot participate
Key Custody Revoke compromised key R-SO + R-LC Cannot participate
Break-glass Approve emergency override R-SO Cannot participate
Production Promotion Final go/no-go for release R-RM Recommend only
Architecture Breaking Change Approve cross-boundary change R-AG Recommend only

Enforcement Policy:

1
2
3
4
5
6
7
8
9
10
Policy NonDelegableDecisionEnforcement:
  applies_to: [all_transactions]

  rule BlockAutomatedApproval:
    when:
      - transaction.type IN NonDelegableDecisionTypes
      - transaction.approver.role == "R-AA"
    then:
      - REJECT with "Non-delegable decision: Human approval required"
      - EMIT AuditEvent(type: "governance.authority.automated-approval-blocked")

7. Agent HITL Escalation Protocol

This section defines the Human-in-the-Loop (HITL) escalation protocol for AI agents (R-AA) performing privileged actions.

7.1. Escalation Request Schema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "AgentEscalationRequest",
  "description": "Request for human approval of agent-initiated privileged action.",
  "type": "object",
  "required": [
    "escalationId",
    "agentId",
    "action",
    "requiredApproverRole",
    "context",
    "createdAt"
  ],
  "properties": {
    "escalationId": {
      "type": "string",
      "format": "uuid",
      "description": "Unique identifier for this escalation request"
    },
    "agentId": {
      "type": "string",
      "pattern": "^principal:agent:[a-z-]+:[a-f0-9-]+$",
      "description": "Agent principal requesting escalation"
    },
    "sponsorId": {
      "type": "string",
      "description": "Human principal who authorized the agent's task"
    },
    "action": {
      "type": "object",
      "required": ["type", "target", "description"],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "file_write",
            "file_delete",
            "command_execute",
            "external_request",
            "state_mutation",
            "deployment",
            "secret_access"
          ]
        },
        "target": {
          "type": "string",
          "description": "Resource being affected"
        },
        "description": {
          "type": "string",
          "description": "Human-readable description of the action"
        },
        "risk": {
          "type": "string",
          "enum": ["low", "medium", "high", "critical"]
        },
        "reversible": {
          "type": "boolean"
        }
      }
    },
    "requiredApproverRole": {
      "type": "string",
      "enum": ["R-DS", "R-AG", "R-LC", "R-SO", "R-RM", "R-DEV"],
      "description": "Minimum role required to approve this action"
    },
    "context": {
      "type": "object",
      "properties": {
        "taskId": { "type": "string" },
        "conversationId": { "type": "string" },
        "boundedContext": { "type": "string" },
        "relatedArtifacts": {
          "type": "array",
          "items": { "type": "string" }
        },
        "rationale": { "type": "string" }
      }
    },
    "status": {
      "type": "string",
      "enum": ["pending", "approved", "rejected", "expired", "cancelled"]
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "expiresAt": {
      "type": "string",
      "format": "date-time"
    },
    "decision": {
      "type": "object",
      "properties": {
        "approver": { "type": "string" },
        "approverRole": { "type": "string" },
        "decidedAt": { "type": "string", "format": "date-time" },
        "rationale": { "type": "string" }
      }
    }
  }
}

7.2. Escalation Triggers

Action Type Trigger Condition Required Approver
file_write Writing to protected paths (e.g., libs/*/src/lib/**) R-DEV
file_delete Any file deletion R-DEV
command_execute Commands with side effects (not marked SafeToAutoRun) R-DEV
external_request Non-whitelisted external API calls R-SO
state_mutation Database or state store modifications R-DS
deployment Any deployment action R-RM
secret_access Accessing secrets or credentials R-SO

7.3. Approval Workflow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──────────────┐    create_escalation()    ┌─────────────┐
│ Agent (R-AA) │ ──────────────────────────► │   pending   │
└──────────────┘                            └─────────────┘
                                                   │
                                     ┌─────────────┼─────────────┐
                                     │             │             │
                              approve()      reject()       timeout()
                                     │             │             │
                                     ▼             ▼             ▼
                              ┌──────────┐ ┌──────────┐ ┌──────────┐
                              │ approved │ │ rejected │ │ expired  │
                              └──────────┘ └──────────┘ └──────────┘
                                     │
                           execute_action()
                                     │
                                     ▼
                              ┌───────────────┐
                              │ action_logged │
                              └───────────────┘

7.4. Invariants

INV-ID Invariant Enforcement
INV-HITL-01 Agents CANNOT self-approve escalations approver.principalId != agentId
INV-HITL-02 Escalation sponsor SHOULD NOT be the approver Warning if sponsorId == approver
INV-HITL-03 Expired escalations CANNOT be approved Status check before approval
INV-HITL-04 All approved actions MUST be logged Audit event emission required
INV-HITL-05 High-risk actions require explicit acknowledgment UI checkbox for risk > medium

7.5. Audit Events

Event Type Trigger Required Fields
governance.agent.escalation-created Escalation request created escalationId, agentId, action, timestamp
governance.agent.escalation-approved Human approves escalation escalationId, approver, role, rationale, timestamp
governance.agent.escalation-rejected Human rejects escalation escalationId, rejector, role, reason, timestamp
governance.agent.escalation-expired Escalation times out escalationId, expiresAt, timestamp
governance.agent.action-executed Approved action executed escalationId, actionType, target, result, timestamp

7.6. Integration with SDS-052 (Tool Surface)

The HITL escalation protocol integrates with the MCP tool surface defined in SDS-052:

7.7. Default Timeouts

Risk Level Default Timeout Maximum Extension
low 30 minutes 2 hours
medium 15 minutes 1 hour
high 5 minutes 30 minutes
critical 2 minutes 10 minutes

8. Mandatory Audit Artifacts

Every privileged action MUST emit an audit event to the IFL. The following event types and required fields are normative.

8.1. Event Type Catalog

Event Type Trigger Required Fields
governance.authority.proposal-submitted SemanticChangeProposal enters submitted proposalId, author, type, scope, timestamp
governance.authority.proposal-approved Proposal transitions to approved proposalId, approver, role, rationale, timestamp
governance.authority.proposal-rejected Proposal transitions to rejected proposalId, rejector, role, reason, timestamp
governance.authority.proposal-enacted Proposal transitions to enacted proposalId, enactor, ledgerEntryId, timestamp
governance.authority.debt-accepted SemanticDebt transitions to accepted debtId, acceptor, role, severity, expiration, rationale, timestamp
governance.authority.debt-expired SemanticDebt auto-expires debtId, originalAcceptor, expirationDate, timestamp
governance.authority.break-glass-requested Break-glass request created breakGlassId, requester, reason, scope, timestamp
governance.authority.break-glass-approved Break-glass approved breakGlassId, approver, expiresAt, timestamp
governance.authority.break-glass-expired Break-glass window closed breakGlassId, duration, actionsPerformed, timestamp
governance.authority.break-glass-revoked Break-glass manually revoked breakGlassId, revoker, reason, timestamp
governance.authority.mint-requested Mint request created mintRequestId, sourceHash, artifactType, requester, timestamp
governance.authority.mint-signed Mint signature applied mintRequestId, sourceHash, signer, role, timestamp
governance.authority.mint-committed Binding record committed to IFL mintRequestId, sourceHash, targetToken, ledgerEntryId, timestamp
governance.authority.key-rotated Signing key rotated keyId, oldKeyHash, newKeyHash, operator, approver, reason, timestamp
governance.authority.key-revoked Signing key revoked (emergency) keyId, keyHash, revoker, reason, timestamp
governance.authority.node-added IFL node added nodeId, operator, approver, timestamp
governance.authority.node-removed IFL node removed nodeId, operator, approver, reason, timestamp
governance.authority.sod-violation-blocked SoD rule blocked a transaction transactionId, violatedRule, actor, timestamp

8.2. Audit Event Schema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "GovernanceAuthorityAuditEvent",
  "type": "object",
  "properties": {
    "specversion": { "const": "1.0" },
    "id": { "type": "string", "format": "uuid" },
    "type": {
      "type": "string",
      "pattern": "^governance\\.authority\\.[a-z-]+$"
    },
    "source": { "type": "string", "const": "//core/authority-service" },
    "time": { "type": "string", "format": "date-time" },
    "data": {
      "type": "object",
      "required": ["actor", "action"],
      "properties": {
        "actor": {
          "type": "object",
          "required": ["principalId", "role"],
          "properties": {
            "principalId": { "type": "string" },
            "role": {
              "type": "string",
              "enum": ["R-DS", "R-AG", "R-LC", "R-SO", "R-RM", "R-DEV", "R-AA"]
            }
          }
        },
        "action": { "type": "string" }
      },
      "additionalProperties": true
    }
  },
  "required": ["specversion", "id", "type", "source", "time", "data"]
}

8.3. Retention Policy

Event Category Retention Period Storage Tier
Break-glass events 7 years Cold (compliance)
Key management events 7 years Cold (compliance)
Proposal lifecycle 3 years Warm
Debt acceptance 3 years Warm
Mint/attest Indefinite Hot (provenance)
SoD violations 7 years Cold (compliance)

9. Emergency Procedures

9.1. Key Compromise Response

Trigger: Suspicion or confirmation that a signing key has been compromised.

Playbook:

  1. Immediate (0-15 min):

  2. Short-term (15 min - 4 hours):

  3. Recovery (4-24 hours):

  4. Post-Incident (24-72 hours):

9.2. Ledger Inconsistency Recovery

Trigger: Detected divergence between IFL nodes or hash mismatch in Merkle proof.

Playbook:

  1. Immediate (0-15 min):

  2. Diagnosis (15 min - 2 hours):

  3. Resolution:

  4. Restoration:

9.3. Malicious Actor Containment

Trigger: Detection of intentional policy violation or unauthorized privileged action.

Playbook:

  1. Immediate (0-5 min):

  2. Containment (5-30 min):

  3. Remediation:

  4. Closure:

9.4. Rollback Protocol

Trigger: Critical defect in production requiring immediate version rollback.

Constraints:

Playbook:

  1. Initiation:

  2. Execution:

  3. Post-Rollback:


10. Implementation Notes

10.1. Principal Identity

Principals are identified by:

10.2. Role Binding Storage

Role bindings are stored in the IFL as RoleBinding entities:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "bindingId": "uuid",
  "principalId": "principal:human:github:user123",
  "role": "R-DS",
  "scope": {
    "type": "bounded_context",
    "value": "com.example.billing"
  },
  "grantedBy": "principal:human:github:admin456",
  "grantedAt": "ISO8601",
  "expiresAt": "ISO8601 | null",
  "revoked": false
}

10.3. Integration Points

System Integration
sea-gate (CI) Enforces SoD rules, checks role permissions before proposal approval
IFL Service (SDS-050) Stores role bindings, emits audit events, enforces transaction signatures
Identity Service (SDS-050) Maps principals to public keys for signature verification
Semantic Debt Ledger (SDS-016) Applies acceptance constraints from this spec
Delivery Pipeline (SDS-021) Enforces promotion authority via R-RM role check

Note: SDS-031 (Semantic Change Workflow) has been consolidated into §5 of this specification.


12. Changelog

Version Date Author Change
0.1.0 2025-12-22 SEA-Forge™ Initial draft
0.2.0 2025-12-22 SEA-Forge™ Added: 4-eyes rule invariants (I-SCP-04, I-SCP-05), approval expiry & version binding schema, capability token integration
0.3.0 2025-12-31 SEA-Forge™ Consolidated SDS-031 (Semantic Change Workflow) into §5 Decision Execution; supersedes SDS-031
0.4.0 2026-01-02 SEA-Forge™ Added §7 Agent HITL Escalation Protocol; fixed duplicate §6 numbering; renumbered sections 7-11 to 8-12