engineering-platform 2.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +32 -0
  2. engineering_platform/ENGINEERING_PLATFORM_VERSION.json +15 -0
  3. engineering_platform/__init__.py +1 -0
  4. engineering_platform/__main__.py +7 -0
  5. engineering_platform/agent_state.py +530 -0
  6. engineering_platform/agent_trust.py +174 -0
  7. engineering_platform/assets/dashboard.css +1317 -0
  8. engineering_platform/assets/dashboard.js +8534 -0
  9. engineering_platform/assets/dashboard_locales.mjs +4049 -0
  10. engineering_platform/assets/dashboard_status_store.mjs +41 -0
  11. engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
  12. engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
  13. engineering_platform/assets/operations-console/icon-dark.png +0 -0
  14. engineering_platform/assets/operations-console/icon-light.png +0 -0
  15. engineering_platform/assets/operations-console/icon-transparent.png +0 -0
  16. engineering_platform/assets/operations-console/manifest.webmanifest +11 -0
  17. engineering_platform/capability_preflight.py +285 -0
  18. engineering_platform/capability_review.py +261 -0
  19. engineering_platform/central_data_transfer.py +195 -0
  20. engineering_platform/central_database.py +245 -0
  21. engineering_platform/central_store_migration.py +1672 -0
  22. engineering_platform/codex_capacity.py +81 -0
  23. engineering_platform/codex_chat.py +226 -0
  24. engineering_platform/codex_observability.py +153 -0
  25. engineering_platform/component_lock.py +40 -0
  26. engineering_platform/component_logging.py +420 -0
  27. engineering_platform/console_presentation.py +14 -0
  28. engineering_platform/console_route_ownership.py +83 -0
  29. engineering_platform/contracts/__init__.py +38 -0
  30. engineering_platform/contracts/ep_consumer.py +391 -0
  31. engineering_platform/contracts/models.py +105 -0
  32. engineering_platform/contracts/projection.py +401 -0
  33. engineering_platform/dashboard_browser_validation.py +206 -0
  34. engineering_platform/dashboard_state.py +630 -0
  35. engineering_platform/dashboard_supervisor.swift +105 -0
  36. engineering_platform/dashboard_translation.py +129 -0
  37. engineering_platform/dependabot_producer.py +349 -0
  38. engineering_platform/drift_diagnostics.py +144 -0
  39. engineering_platform/emergency_recovery.py +268 -0
  40. engineering_platform/engineering_memory.py +139 -0
  41. engineering_platform/ep_consumer_credentials.py +473 -0
  42. engineering_platform/evidence_projection.py +213 -0
  43. engineering_platform/execution_activity.py +218 -0
  44. engineering_platform/execution_context.py +132 -0
  45. engineering_platform/execution_errors.py +42 -0
  46. engineering_platform/execution_evidence.py +24 -0
  47. engineering_platform/execution_executor.py +730 -0
  48. engineering_platform/execution_finalization.py +44 -0
  49. engineering_platform/execution_host.py +3306 -0
  50. engineering_platform/execution_lease.py +365 -0
  51. engineering_platform/execution_lifecycle.py +447 -0
  52. engineering_platform/execution_models.py +43 -0
  53. engineering_platform/execution_readiness.py +166 -0
  54. engineering_platform/execution_reporting.py +1607 -0
  55. engineering_platform/execution_repository.py +253 -0
  56. engineering_platform/execution_timeout_policy.py +56 -0
  57. engineering_platform/execution_timing.py +440 -0
  58. engineering_platform/execution_transaction.py +28 -0
  59. engineering_platform/external_producer_binding.py +235 -0
  60. engineering_platform/file_inbox.py +249 -0
  61. engineering_platform/forensic_attribution.py +338 -0
  62. engineering_platform/forensic_attribution_v2.py +134 -0
  63. engineering_platform/forensic_delta.py +299 -0
  64. engineering_platform/golden_scenario.py +63 -0
  65. engineering_platform/historical_dashboard_configuration.py +171 -0
  66. engineering_platform/host_admin.py +199 -0
  67. engineering_platform/host_preflight.py +231 -0
  68. engineering_platform/installation_relocation.py +122 -0
  69. engineering_platform/investigation_ledger.py +89 -0
  70. engineering_platform/legacy_inbox_migration.py +79 -0
  71. engineering_platform/lifecycle_worker.py +223 -0
  72. engineering_platform/live_status.py +267 -0
  73. engineering_platform/local_api.py +209 -0
  74. engineering_platform/local_api_keychain.py +51 -0
  75. engineering_platform/local_repository_binding.py +138 -0
  76. engineering_platform/managed_autonomy.py +509 -0
  77. engineering_platform/managed_codex_runtime.py +105 -0
  78. engineering_platform/parity_context.py +203 -0
  79. engineering_platform/parity_lifecycle_dispatcher.py +488 -0
  80. engineering_platform/platform_admin.py +13 -0
  81. engineering_platform/platform_api.py +428 -0
  82. engineering_platform/platform_bootstrap.py +385 -0
  83. engineering_platform/platform_components.py +65 -0
  84. engineering_platform/platform_version.py +171 -0
  85. engineering_platform/pr_check_repair.py +276 -0
  86. engineering_platform/pr_evidence_backfill.py +278 -0
  87. engineering_platform/producer.py +209 -0
  88. engineering_platform/project_agent.py +366 -0
  89. engineering_platform/project_agent_service.py +244 -0
  90. engineering_platform/project_topology.py +126 -0
  91. engineering_platform/prompt_history.py +591 -0
  92. engineering_platform/provider_context.py +136 -0
  93. engineering_platform/provider_context_benchmark.py +41 -0
  94. engineering_platform/provider_context_scope.py +90 -0
  95. engineering_platform/provider_interruption.py +168 -0
  96. engineering_platform/provider_process_identity.py +80 -0
  97. engineering_platform/provider_readiness.py +138 -0
  98. engineering_platform/provider_recovery.py +647 -0
  99. engineering_platform/provider_usage.py +497 -0
  100. engineering_platform/providers.py +471 -0
  101. engineering_platform/qualification.py +220 -0
  102. engineering_platform/recommendation_handoff.py +238 -0
  103. engineering_platform/report_analysis.py +193 -0
  104. engineering_platform/repository_attachment.py +171 -0
  105. engineering_platform/repository_handoff.py +95 -0
  106. engineering_platform/resources.py +38 -0
  107. engineering_platform/reviewer_evidence.py +70 -0
  108. engineering_platform/schemas/repository-attachment.schema.json +61 -0
  109. engineering_platform/server.py +3679 -0
  110. engineering_platform/server_console_services.py +2024 -0
  111. engineering_platform/server_relay.py +172 -0
  112. engineering_platform/server_service.py +122 -0
  113. engineering_platform/status_model.py +135 -0
  114. engineering_platform/status_reconciliation.py +34 -0
  115. engineering_platform/storage.py +2440 -0
  116. engineering_platform/submission_cli.py +77 -0
  117. engineering_platform/submission_intake.py +45 -0
  118. engineering_platform/submission_service.py +317 -0
  119. engineering_platform/telemetry.py +951 -0
  120. engineering_platform/templates/workspace-config.json +25 -0
  121. engineering_platform/validation_identity.py +50 -0
  122. engineering_platform/validation_profile.py +211 -0
  123. engineering_platform/workspace_preflight.py +263 -0
  124. engineering_platform/worktree_provenance.py +147 -0
  125. engineering_platform/worktree_tooling.py +18 -0
  126. engineering_platform-2.2.0.dist-info/METADATA +18 -0
  127. engineering_platform-2.2.0.dist-info/RECORD +130 -0
  128. engineering_platform-2.2.0.dist-info/WHEEL +5 -0
  129. engineering_platform-2.2.0.dist-info/entry_points.txt +6 -0
  130. engineering_platform-2.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,473 @@
1
+ """Verifier-only Engineering Platform consumer credentials and qualification seam.
2
+
3
+ Increment 2a permits one short-lived, operator-created qualification credential.
4
+ It is not consumer registration or a general credential-issuance workflow.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ from collections.abc import Callable
11
+ from dataclasses import dataclass, field
12
+ from datetime import datetime, timedelta, timezone
13
+ import hashlib
14
+ import hmac
15
+ import json
16
+ from pathlib import Path
17
+ import secrets
18
+
19
+ from .contracts.ep_consumer import RequestEnvelope
20
+ from .storage import open_storage
21
+
22
+ # These fixed predecessor domains preserve existing verifier and fingerprint
23
+ # values during the namespace migration. Renaming the domains would invalidate
24
+ # otherwise valid bearer credentials, so the opaque values are intentionally
25
+ # retained as migration compatibility material rather than current authority.
26
+ VERIFIER_DOMAIN = b"engineering-platform.local-api.verifier.v1\0"
27
+ FINGERPRINT_DOMAIN = b"engineering-platform.local-api.fingerprint.v1\0"
28
+ QUALIFICATION_PREFIX = "qualification-"
29
+ QUALIFICATION_TTL = timedelta(minutes=15)
30
+ PRODUCTION_PREFIX = "production-"
31
+ MAX_ACTIVE_PRODUCTION_CREDENTIALS = 2
32
+
33
+
34
+ def verifier(credential: str) -> bytes:
35
+ return hashlib.sha256(VERIFIER_DOMAIN + credential.encode("ascii")).digest()
36
+
37
+
38
+ def fingerprint(credential: str) -> bytes:
39
+ return hashlib.sha256(FINGERPRINT_DOMAIN + credential.encode("ascii")).digest()
40
+
41
+
42
+ def _timestamp(value: datetime) -> str:
43
+ return value.astimezone(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
44
+
45
+
46
+ def _scope(consumer_id: str, project_id: str) -> tuple[str, str]:
47
+ """Reuse the v1 contract validator rather than duplicating identity rules."""
48
+
49
+ envelope = RequestEnvelope.parse(
50
+ {
51
+ "contract_version": "1.0",
52
+ "request_type": "contract.foundation",
53
+ "request_id": "qualification-credential",
54
+ "project_id": project_id,
55
+ "consumer": {"consumer_id": consumer_id},
56
+ "auth": {"scheme": "bearer", "credential": "operator-carrier"},
57
+ "payload": {},
58
+ }
59
+ )
60
+ return envelope.consumer.consumer_id, envelope.project_id
61
+
62
+
63
+ @dataclass(frozen=True)
64
+ class CredentialScope:
65
+ consumer_id: str
66
+ project_id: str
67
+ verifier_value: bytes
68
+
69
+
70
+ @dataclass(frozen=True)
71
+ class QualificationCredential:
72
+ credential_id: str
73
+ consumer_id: str
74
+ project_id: str
75
+ fingerprint_hex: str
76
+ created_at: str
77
+ expires_at: str
78
+ credential: str = field(repr=False)
79
+
80
+ def disclosure(self) -> dict[str, str]:
81
+ """The sole plaintext handoff, used only by the create CLI command."""
82
+
83
+ return {
84
+ "credential_id": self.credential_id,
85
+ "consumer_id": self.consumer_id,
86
+ "project_id": self.project_id,
87
+ "purpose": "QUALIFICATION",
88
+ "created_at": self.created_at,
89
+ "expires_at": self.expires_at,
90
+ "credential": self.credential,
91
+ }
92
+
93
+
94
+ def create_qualification_credential(
95
+ root: Path, *, consumer_id: str, project_id: str, now: datetime | None = None
96
+ ) -> QualificationCredential:
97
+ """Create the one active, short-lived qualification credential."""
98
+
99
+ consumer_id, project_id = _scope(consumer_id, project_id)
100
+ moment = now or datetime.now(timezone.utc)
101
+ created_at = _timestamp(moment)
102
+ expires_at = _timestamp(moment + QUALIFICATION_TTL)
103
+ credential = secrets.token_urlsafe(32)
104
+ credential_id = QUALIFICATION_PREFIX + secrets.token_hex(16)
105
+ candidate_verifier = verifier(credential)
106
+ candidate_fingerprint = fingerprint(credential)
107
+ connection = open_storage(root)
108
+ try:
109
+ active = connection.execute(
110
+ "SELECT 1 FROM ep_consumer_credentials WHERE credential_id LIKE ? "
111
+ "AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at>CURRENT_TIMESTAMP) LIMIT 1",
112
+ (f"{QUALIFICATION_PREFIX}%",),
113
+ ).fetchone()
114
+ if active is not None:
115
+ raise ValueError("An active qualification credential already exists; revoke it first.")
116
+ connection.execute(
117
+ "INSERT INTO ep_consumer_credentials(credential_id,consumer_id,project_id,verifier,fingerprint,issued_at,expires_at) "
118
+ "VALUES(?,?,?,?,?,?,?)",
119
+ (
120
+ credential_id,
121
+ consumer_id,
122
+ project_id,
123
+ candidate_verifier,
124
+ candidate_fingerprint,
125
+ created_at,
126
+ expires_at,
127
+ ),
128
+ )
129
+ finally:
130
+ connection.close()
131
+ return QualificationCredential(
132
+ credential_id=credential_id,
133
+ consumer_id=consumer_id,
134
+ project_id=project_id,
135
+ fingerprint_hex=candidate_fingerprint.hex(),
136
+ created_at=created_at,
137
+ expires_at=expires_at,
138
+ credential=credential,
139
+ )
140
+
141
+
142
+ def qualification_status(root: Path) -> list[dict[str, str | bool | None]]:
143
+ """Return safe, bounded qualification metadata without token material."""
144
+
145
+ connection = open_storage(root)
146
+ try:
147
+ rows = connection.execute(
148
+ "SELECT credential_id,consumer_id,project_id,fingerprint,issued_at,expires_at,revoked_at "
149
+ "FROM ep_consumer_credentials WHERE credential_id LIKE ? ORDER BY issued_at DESC",
150
+ (f"{QUALIFICATION_PREFIX}%",),
151
+ ).fetchall()
152
+ finally:
153
+ connection.close()
154
+ now = _timestamp(datetime.now(timezone.utc))
155
+ return [
156
+ {
157
+ "credential_id": str(row[0]),
158
+ "consumer_id": str(row[1]),
159
+ "project_id": str(row[2]),
160
+ "fingerprint": bytes(row[3]).hex(),
161
+ "purpose": "QUALIFICATION",
162
+ "created_at": str(row[4]),
163
+ "expires_at": str(row[5]) if row[5] is not None else None,
164
+ "active": row[6] is None and (row[5] is None or str(row[5]) > now),
165
+ "revoked_at": str(row[6]) if row[6] is not None else None,
166
+ }
167
+ for row in rows
168
+ ]
169
+
170
+
171
+ def revoke_qualification_credential(root: Path, credential_id: str) -> bool:
172
+ """Explicitly deactivate a qualification credential without deleting evidence."""
173
+
174
+ if not credential_id.startswith(QUALIFICATION_PREFIX):
175
+ raise ValueError("credential_id is not a qualification credential.")
176
+ connection = open_storage(root)
177
+ try:
178
+ result = connection.execute(
179
+ "UPDATE ep_consumer_credentials SET revoked_at=? WHERE credential_id=? AND revoked_at IS NULL",
180
+ (_timestamp(datetime.now(timezone.utc)), credential_id),
181
+ )
182
+ return result.rowcount == 1
183
+ finally:
184
+ connection.close()
185
+
186
+
187
+ def _registration(root: Path, consumer_id: str, project_id: str) -> tuple[str, ...] | None:
188
+ connection = open_storage(root)
189
+ try:
190
+ return connection.execute(
191
+ "SELECT consumer_id,project_id,status,created_at,updated_at,disabled_at,revoked_at "
192
+ "FROM ep_consumer_registrations WHERE consumer_id=? AND project_id=?",
193
+ (consumer_id, project_id),
194
+ ).fetchone()
195
+ finally:
196
+ connection.close()
197
+
198
+
199
+ def register_consumer(root: Path, *, consumer_id: str, project_id: str) -> dict[str, str | bool | None]:
200
+ consumer_id, project_id = _scope(consumer_id, project_id)
201
+ now = _timestamp(datetime.now(timezone.utc))
202
+ connection = open_storage(root)
203
+ try:
204
+ row = connection.execute(
205
+ "SELECT status,created_at,updated_at,disabled_at,revoked_at FROM ep_consumer_registrations "
206
+ "WHERE consumer_id=? AND project_id=?", (consumer_id, project_id)
207
+ ).fetchone()
208
+ if row is None:
209
+ connection.execute(
210
+ "INSERT INTO ep_consumer_registrations(consumer_id,project_id,status,created_at,updated_at,audit_metadata) "
211
+ "VALUES(?,?, 'ACTIVE',?,?,?)", (consumer_id, project_id, now, now, json.dumps({"action":"REGISTER"}, sort_keys=True))
212
+ )
213
+ return {"consumer_id":consumer_id,"project_id":project_id,"status":"ACTIVE","created_at":now,"updated_at":now,"idempotent":False}
214
+ if row[0] != "ACTIVE":
215
+ raise ValueError("consumer registration is not active.")
216
+ return {"consumer_id":consumer_id,"project_id":project_id,"status":"ACTIVE","created_at":str(row[1]),"updated_at":str(row[2]),"idempotent":True}
217
+ finally:
218
+ connection.close()
219
+
220
+
221
+ def consumer_status(root: Path, *, consumer_id: str, project_id: str) -> dict[str, object]:
222
+ consumer_id, project_id = _scope(consumer_id, project_id)
223
+ row = _registration(root, consumer_id, project_id)
224
+ if row is None:
225
+ raise ValueError("consumer registration is absent.")
226
+ connection = open_storage(root)
227
+ try:
228
+ count = connection.execute(
229
+ "SELECT count(*) FROM ep_consumer_credentials WHERE consumer_id=? AND project_id=? AND credential_id LIKE ? "
230
+ "AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at>CURRENT_TIMESTAMP)",
231
+ (consumer_id, project_id, f"{PRODUCTION_PREFIX}%"),
232
+ ).fetchone()[0]
233
+ finally:
234
+ connection.close()
235
+ return {"consumer_id":row[0],"project_id":row[1],"status":row[2],"created_at":row[3],"updated_at":row[4],"disabled_at":row[5],"revoked_at":row[6],"active_production_credentials":count}
236
+
237
+
238
+ def _set_registration_state(root: Path, *, consumer_id: str, project_id: str, state: str) -> bool:
239
+ consumer_id, project_id = _scope(consumer_id, project_id)
240
+ now = _timestamp(datetime.now(timezone.utc))
241
+ column = "disabled_at" if state == "DISABLED" else "revoked_at"
242
+ connection = open_storage(root)
243
+ try:
244
+ result = connection.execute(
245
+ f"UPDATE ep_consumer_registrations SET status=?,updated_at=?,{column}=?,audit_metadata=? "
246
+ "WHERE consumer_id=? AND project_id=? AND status='ACTIVE'",
247
+ (state, now, now, json.dumps({"action": "DISABLE" if state == "DISABLED" else "REVOKE_REGISTRATION"}, sort_keys=True), consumer_id, project_id),
248
+ )
249
+ existing = connection.execute("SELECT status FROM ep_consumer_registrations WHERE consumer_id=? AND project_id=?", (consumer_id, project_id)).fetchone()
250
+ if existing is None:
251
+ raise ValueError("consumer registration is absent.")
252
+ if existing[0] != state and result.rowcount != 1:
253
+ raise ValueError("consumer registration state conflicts.")
254
+ return result.rowcount == 1
255
+ finally:
256
+ connection.close()
257
+
258
+
259
+ def disable_consumer(root: Path, *, consumer_id: str, project_id: str) -> bool:
260
+ return _set_registration_state(root, consumer_id=consumer_id, project_id=project_id, state="DISABLED")
261
+
262
+
263
+ def revoke_consumer(root: Path, *, consumer_id: str, project_id: str) -> bool:
264
+ return _set_registration_state(root, consumer_id=consumer_id, project_id=project_id, state="REVOKED")
265
+
266
+
267
+ @dataclass(frozen=True)
268
+ class ProductionCredential:
269
+ credential_id: str
270
+ consumer_id: str
271
+ project_id: str
272
+ fingerprint_hex: str
273
+ created_at: str
274
+ credential: str = field(repr=False)
275
+
276
+ def disclosure(self) -> dict[str, str]:
277
+ return {"credential_id":self.credential_id,"consumer_id":self.consumer_id,"project_id":self.project_id,"purpose":"PRODUCTION_CONSUMER","created_at":self.created_at,"credential":self.credential}
278
+
279
+
280
+ def issue_credential(root: Path, *, consumer_id: str, project_id: str) -> ProductionCredential:
281
+ consumer_id, project_id = _scope(consumer_id, project_id)
282
+ status = _registration(root, consumer_id, project_id)
283
+ if status is None or status[2] != "ACTIVE":
284
+ raise ValueError("active consumer registration is required.")
285
+ token = secrets.token_urlsafe(32)
286
+ now = _timestamp(datetime.now(timezone.utc))
287
+ credential_id = PRODUCTION_PREFIX + secrets.token_hex(16)
288
+ connection = open_storage(root)
289
+ try:
290
+ count = connection.execute("SELECT count(*) FROM ep_consumer_credentials WHERE consumer_id=? AND project_id=? AND credential_id LIKE ? AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at>CURRENT_TIMESTAMP)", (consumer_id,project_id,f"{PRODUCTION_PREFIX}%")).fetchone()[0]
291
+ if count >= MAX_ACTIVE_PRODUCTION_CREDENTIALS:
292
+ raise ValueError("active production credential limit reached.")
293
+ connection.execute("INSERT INTO ep_consumer_credentials(credential_id,consumer_id,project_id,verifier,fingerprint,issued_at) VALUES(?,?,?,?,?,?)", (credential_id,consumer_id,project_id,verifier(token),fingerprint(token),now))
294
+ finally:
295
+ connection.close()
296
+ return ProductionCredential(credential_id,consumer_id,project_id,fingerprint(token).hex(),now,token)
297
+
298
+
299
+ def credential_status(root: Path, *, consumer_id: str, project_id: str) -> list[dict[str, object]]:
300
+ consumer_id, project_id = _scope(consumer_id, project_id)
301
+ connection = open_storage(root)
302
+ try:
303
+ rows = connection.execute("SELECT credential_id,fingerprint,issued_at,expires_at,revoked_at FROM ep_consumer_credentials WHERE consumer_id=? AND project_id=? AND credential_id LIKE ? ORDER BY issued_at DESC", (consumer_id,project_id,f"{PRODUCTION_PREFIX}%")).fetchall()
304
+ finally:
305
+ connection.close()
306
+ now = _timestamp(datetime.now(timezone.utc))
307
+ return [{"credential_id":str(r[0]),"fingerprint":bytes(r[1]).hex(),"purpose":"PRODUCTION_CONSUMER","created_at":str(r[2]),"expires_at":r[3],"revoked_at":r[4],"active":r[4] is None and (r[3] is None or str(r[3]) > now)} for r in rows]
308
+
309
+
310
+ def revoke_credential(root: Path, credential_id: str) -> bool:
311
+ if not credential_id.startswith(PRODUCTION_PREFIX):
312
+ raise ValueError("credential_id is not a production credential.")
313
+ connection = open_storage(root)
314
+ try:
315
+ result = connection.execute("UPDATE ep_consumer_credentials SET revoked_at=? WHERE credential_id=? AND revoked_at IS NULL", (_timestamp(datetime.now(timezone.utc)),credential_id))
316
+ if result.rowcount == 0 and connection.execute(
317
+ "SELECT 1 FROM ep_consumer_credentials WHERE credential_id=?", (credential_id,)
318
+ ).fetchone() is None:
319
+ raise ValueError("production credential is absent.")
320
+ return result.rowcount == 1
321
+ finally:
322
+ connection.close()
323
+
324
+
325
+ def rotate_credential(
326
+ root: Path, *, consumer_id: str, project_id: str, old_credential_id: str,
327
+ store: object, authenticate: Callable[[str], bool],
328
+ ) -> ProductionCredential:
329
+ """Issue, securely store and prove a replacement before revoking the old token."""
330
+ replacement = issue_credential(root, consumer_id=consumer_id, project_id=project_id)
331
+ try:
332
+ store.put_credential(consumer_id, project_id, replacement.credential)
333
+ if not authenticate(replacement.credential):
334
+ raise ValueError("replacement credential did not authenticate.")
335
+ except Exception:
336
+ revoke_credential(root, replacement.credential_id)
337
+ raise
338
+ revoke_credential(root, old_credential_id)
339
+ return replacement
340
+
341
+
342
+ class CredentialAuthority:
343
+ """Read-only production authority with explicit in-memory test fixtures."""
344
+
345
+ def __init__(self, root: Path | None = None, record: CredentialScope | None = None) -> None:
346
+ self.root, self.record = root, record
347
+
348
+ @classmethod
349
+ def test_fixture(
350
+ cls, credential: str, *, consumer_id: str, project_id: str
351
+ ) -> "CredentialAuthority":
352
+ return cls(record=CredentialScope(consumer_id, project_id, verifier(credential)))
353
+
354
+ def ready(self) -> bool:
355
+ if self.root is None:
356
+ return True
357
+ try:
358
+ connection = open_storage(self.root)
359
+ try:
360
+ connection.execute("SELECT 1 FROM ep_consumer_credentials LIMIT 1").fetchone()
361
+ connection.execute("SELECT 1 FROM ep_consumer_registrations LIMIT 1").fetchone()
362
+ finally:
363
+ connection.close()
364
+ return True
365
+ except Exception:
366
+ return False
367
+
368
+ def authenticate(self, credential: str) -> CredentialScope | None:
369
+ try:
370
+ candidate = verifier(credential)
371
+ except UnicodeEncodeError:
372
+ return None
373
+ if self.record is not None:
374
+ return (
375
+ self.record if hmac.compare_digest(self.record.verifier_value, candidate) else None
376
+ )
377
+ if self.root is None:
378
+ return None
379
+ try:
380
+ connection = open_storage(self.root)
381
+ try:
382
+ row = connection.execute(
383
+ "SELECT credential_id,consumer_id,project_id,verifier FROM ep_consumer_credentials "
384
+ "WHERE verifier=? AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at>CURRENT_TIMESTAMP)",
385
+ (candidate,),
386
+ ).fetchone()
387
+ finally:
388
+ connection.close()
389
+ except Exception:
390
+ return None
391
+ if row is None or not hmac.compare_digest(bytes(row[3]), candidate):
392
+ return None
393
+ return CredentialScope(str(row[1]), str(row[2]), bytes(row[3]))
394
+
395
+ def authorized(self, scope: CredentialScope) -> bool:
396
+ """Evaluate current registration state after bearer authentication."""
397
+
398
+ if self.root is None or self.record is not None:
399
+ return True
400
+ try:
401
+ connection = open_storage(self.root)
402
+ try:
403
+ row = connection.execute(
404
+ "SELECT credential_id FROM ep_consumer_credentials WHERE verifier=?",
405
+ (scope.verifier_value,),
406
+ ).fetchone()
407
+ finally:
408
+ connection.close()
409
+ if row is None or not str(row[0]).startswith(PRODUCTION_PREFIX):
410
+ return True
411
+ registration = _registration(self.root, scope.consumer_id, scope.project_id)
412
+ return registration is not None and registration[2] == "ACTIVE"
413
+ except Exception:
414
+ return False
415
+
416
+
417
+ def main(argv: list[str] | None = None) -> int:
418
+ parser = argparse.ArgumentParser(prog="engineering-ep-consumer-credentials")
419
+ parser.add_argument(
420
+ "command",
421
+ choices=(
422
+ "create-qualification-credential",
423
+ "qualification-status",
424
+ "revoke-qualification-credential", "consumer-register", "consumer-status",
425
+ "consumer-disable", "consumer-revoke", "credential-issue", "credential-status", "credential-revoke",
426
+ ),
427
+ )
428
+ parser.add_argument("--repo", type=Path, default=Path.cwd())
429
+ parser.add_argument("--consumer-id")
430
+ parser.add_argument("--project-id")
431
+ parser.add_argument("--credential-id")
432
+ args = parser.parse_args(argv)
433
+ root = args.repo.resolve()
434
+ try:
435
+ if args.command == "create-qualification-credential":
436
+ if args.consumer_id is None or args.project_id is None:
437
+ raise ValueError("--consumer-id and --project-id are required.")
438
+ print(
439
+ json.dumps(
440
+ create_qualification_credential(
441
+ root, consumer_id=args.consumer_id, project_id=args.project_id
442
+ ).disclosure(),
443
+ sort_keys=True,
444
+ )
445
+ )
446
+ return 0
447
+ if args.command == "qualification-status":
448
+ print(json.dumps(qualification_status(root), sort_keys=True))
449
+ return 0
450
+ if args.command in {"consumer-register", "consumer-status", "consumer-disable", "consumer-revoke", "credential-issue", "credential-status"}:
451
+ if args.consumer_id is None or args.project_id is None:
452
+ raise ValueError("--consumer-id and --project-id are required.")
453
+ actions = {"consumer-register": register_consumer, "consumer-status": consumer_status, "consumer-disable": disable_consumer, "consumer-revoke": revoke_consumer, "credential-issue": issue_credential, "credential-status": credential_status}
454
+ result = actions[args.command](root, consumer_id=args.consumer_id, project_id=args.project_id)
455
+ if isinstance(result, (ProductionCredential, QualificationCredential)):
456
+ result = result.disclosure()
457
+ print(json.dumps(result, sort_keys=True))
458
+ return 0
459
+ if args.credential_id is None:
460
+ raise ValueError("--credential-id is required.")
461
+ if args.command == "credential-revoke":
462
+ changed = revoke_credential(root, args.credential_id)
463
+ else:
464
+ changed = revoke_qualification_credential(root, args.credential_id)
465
+ print(json.dumps({"credential_id": args.credential_id, "revoked": True, "changed": changed}, sort_keys=True))
466
+ return 0
467
+ except ValueError as error:
468
+ print(f"ERROR: {error}")
469
+ return 2
470
+
471
+
472
+ if __name__ == "__main__":
473
+ raise SystemExit(main())
@@ -0,0 +1,213 @@
1
+ """Invocation-local bounded projections for oversized shell evidence.
2
+
3
+ The Engineering runner never persists raw tool output. Codex executes shell
4
+ tools inside its own provider turn, so the temporary PATH proxy created here is
5
+ the only safe interception point: it preserves exit status, returns small or
6
+ source output unchanged, and makes an explicit raw expansion available only to
7
+ the same invocation via ``ENGINEERING_PLATFORM_EVIDENCE_EXPAND=1``.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ import os
13
+ from pathlib import Path
14
+ import json
15
+ import shutil
16
+ import subprocess # nosec B404
17
+ import sys
18
+ from tempfile import TemporaryDirectory
19
+ from typing import Iterable, Mapping
20
+
21
+
22
+ # Limits are category-specific because passing logs are repetitive, while a
23
+ # failure needs an assertion, traceback and surrounding context to be useful.
24
+ PASSING_TEST_LIMIT = 768
25
+ FAILED_DIAGNOSTIC_LIMIT = 12_288
26
+ SEARCH_MATCH_LIMIT = 24
27
+ SEARCH_LINE_LIMIT = 240
28
+ GIT_FACT_LIMIT = 2_048
29
+ GITHUB_FACT_LIMIT = 4_096
30
+ PROXIED_TOOLS = ("git", "gh", "rg", "grep", "pytest", "python", "python3", "npm", "npx", "engineering-platform-context-escalate")
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class EvidenceProjection:
35
+ category: str
36
+ text: str
37
+ raw_bytes: int
38
+ projected_bytes: int
39
+ more_evidence_available: bool
40
+
41
+
42
+ def category_for(command: Iterable[str]) -> str:
43
+ values = tuple(command)
44
+ executable = Path(values[0]).name if values else ""
45
+ normalized = " ".join(values).casefold()
46
+ if executable in {"rg", "grep"}:
47
+ return "search"
48
+ if executable == "git":
49
+ return "git"
50
+ if executable == "gh":
51
+ return "github"
52
+ if executable in {"pytest", "npm", "npx"} or (
53
+ executable in {"python", "python3"} and "unittest" in normalized
54
+ ):
55
+ return "test"
56
+ return "other"
57
+
58
+
59
+ def _bytes(value: str) -> int:
60
+ return len(value.encode("utf-8"))
61
+
62
+
63
+ def _bounded_lines(value: str, *, count: int, width: int) -> str:
64
+ return "\n".join(line[:width] for line in value.splitlines()[:count])
65
+
66
+
67
+ def _failure_tail(value: str) -> str:
68
+ lines = value.splitlines()
69
+ if _bytes(value) <= FAILED_DIAGNOSTIC_LIMIT:
70
+ return value
71
+ head = "\n".join(lines[:30])
72
+ tail = "\n".join(lines[-90:])
73
+ return f"{head}\n… FAILED_DIAGNOSTIC_MIDDLE_OMITTED …\n{tail}"[-FAILED_DIAGNOSTIC_LIMIT:]
74
+
75
+
76
+ def project_output(command: Iterable[str], output: str, exit_code: int) -> EvidenceProjection:
77
+ """Project one completed command without losing the raw expansion path."""
78
+ category = category_for(command)
79
+ raw_bytes = _bytes(output)
80
+ if not output or category == "other":
81
+ return EvidenceProjection(category, output, raw_bytes, raw_bytes, False)
82
+ if category == "test":
83
+ if exit_code:
84
+ text = _failure_tail(output)
85
+ more = text != output
86
+ if more:
87
+ marker = "\nMORE_EVIDENCE_AVAILABLE: set ENGINEERING_PLATFORM_EVIDENCE_EXPAND=1 for this command."
88
+ text = f"{text[:FAILED_DIAGNOSTIC_LIMIT - _bytes(marker)]}{marker}"
89
+ elif raw_bytes > PASSING_TEST_LIMIT:
90
+ passed = next((line for line in output.splitlines() if "passed" in line.casefold()), "PASS")
91
+ text = f"PASSING_TEST_OUTPUT_BOUNDED\n{passed[:PASSING_TEST_LIMIT // 2]}\nMORE_EVIDENCE_AVAILABLE: set ENGINEERING_PLATFORM_EVIDENCE_EXPAND=1 for this command."
92
+ more = True
93
+ else:
94
+ text, more = output, False
95
+ elif category == "search" and len(output.splitlines()) > SEARCH_MATCH_LIMIT:
96
+ text = _bounded_lines(output, count=SEARCH_MATCH_LIMIT, width=SEARCH_LINE_LIMIT)
97
+ text += f"\nMATCHES_BOUNDED: shown={SEARCH_MATCH_LIMIT} total={len(output.splitlines())}\nMORE_EVIDENCE_AVAILABLE: set ENGINEERING_PLATFORM_EVIDENCE_EXPAND=1 for this command."
98
+ more = True
99
+ elif category == "git" and raw_bytes > GIT_FACT_LIMIT:
100
+ text = _bounded_lines(output, count=32, width=SEARCH_LINE_LIMIT)
101
+ text += "\nGIT_EVIDENCE_BOUNDED\nMORE_EVIDENCE_AVAILABLE: set ENGINEERING_PLATFORM_EVIDENCE_EXPAND=1 for this command."
102
+ more = True
103
+ elif category == "github" and raw_bytes > GITHUB_FACT_LIMIT:
104
+ text = _bounded_lines(output, count=48, width=SEARCH_LINE_LIMIT)
105
+ text += "\nGITHUB_EVIDENCE_BOUNDED\nMORE_EVIDENCE_AVAILABLE: set ENGINEERING_PLATFORM_EVIDENCE_EXPAND=1 for this command."
106
+ more = True
107
+ else:
108
+ text, more = output, False
109
+ return EvidenceProjection(category, text, raw_bytes, _bytes(text), more)
110
+
111
+
112
+ class ToolProxyEnvironment:
113
+ """Temporary PATH proxy. It retains no output after the invocation ends."""
114
+
115
+ def __init__(self) -> None:
116
+ self._temporary: TemporaryDirectory[str] | None = None
117
+
118
+ def __enter__(self) -> Mapping[str, str]:
119
+ self._temporary = TemporaryDirectory(prefix="engineering-platform-evidence-")
120
+ directory = Path(self._temporary.name)
121
+ repository_root = Path(__file__).resolve().parents[2]
122
+ for name in PROXIED_TOOLS:
123
+ launcher = directory / name
124
+ target = "context_escalation_main" if name == "engineering-platform-context-escalate" else "proxy_main"
125
+ launcher.write_text(
126
+ f"#!{sys.executable}\nimport sys\nsys.path.insert(0, {str(repository_root)!r})\nfrom engineering_platform.evidence_projection import {target}\n{target}({name!r})\n",
127
+ encoding="utf-8",
128
+ )
129
+ launcher.chmod(0o700)
130
+ environment = dict(os.environ)
131
+ environment["ENGINEERING_PLATFORM_EVIDENCE_ORIGINAL_PATH"] = environment.get("PATH", os.defpath)
132
+ environment["PATH"] = f"{directory}{os.pathsep}{environment['ENGINEERING_PLATFORM_EVIDENCE_ORIGINAL_PATH']}"
133
+ environment["ENGINEERING_PLATFORM_CONTEXT_ESCALATION_FILE"] = str(directory / "context-escalations.jsonl")
134
+ return environment
135
+
136
+ def __exit__(self, *_: object) -> None:
137
+ if self._temporary is not None:
138
+ self._temporary.cleanup()
139
+ self._temporary = None
140
+
141
+ def context_escalations(self) -> tuple[dict[str, object], ...]:
142
+ if self._temporary is None:
143
+ return ()
144
+ path = Path(self._temporary.name) / "context-escalations.jsonl"
145
+ try:
146
+ return tuple(
147
+ item for line in path.read_text(encoding="utf-8").splitlines()
148
+ if isinstance((item := json.loads(line)), dict)
149
+ )
150
+ except (OSError, json.JSONDecodeError):
151
+ return ()
152
+
153
+
154
+ def proxy_main(name: str | None = None) -> None:
155
+ """Run the proxied command and emit only its bounded invocation-local view."""
156
+ name = name or Path(sys.argv[0]).name
157
+ original_path = os.environ.get("ENGINEERING_PLATFORM_EVIDENCE_ORIGINAL_PATH", os.defpath)
158
+ executable = shutil.which(name, path=original_path)
159
+ if executable is None:
160
+ raise SystemExit(f"Evidence proxy could not resolve {name}.")
161
+ completed = subprocess.run( # nosec B603
162
+ (executable, *sys.argv[1:]), text=True, capture_output=True,
163
+ env={**os.environ, "PATH": original_path}, check=False,
164
+ )
165
+ raw = f"{completed.stdout}{completed.stderr}"
166
+ if os.environ.get("ENGINEERING_PLATFORM_EVIDENCE_EXPAND") == "1":
167
+ sys.stdout.write(raw)
168
+ else:
169
+ sys.stdout.write(project_output((name, *sys.argv[1:]), raw, completed.returncode).text)
170
+ raise SystemExit(completed.returncode)
171
+
172
+
173
+ def context_escalation_main(_: str | None = None) -> None:
174
+ """Validate and record one bounded historical-context escalation."""
175
+ from .provider_context_scope import ContextEscalationReason, ContextEscalationRequest, HistoryBoundaryKind
176
+
177
+ arguments = sys.argv[1:]
178
+ try:
179
+ diagnostic_index = arguments.index("--diagnostic")
180
+ values, diagnostic = arguments[:diagnostic_index], " ".join(arguments[diagnostic_index + 1:])
181
+ if len(values) != 4:
182
+ raise ValueError("Expected REASON BOUNDARY_KIND BOUNDARY LIMIT.")
183
+ request = ContextEscalationRequest(
184
+ ContextEscalationReason(values[0]), HistoryBoundaryKind(values[1]), values[2], int(values[3]), diagnostic
185
+ ).validate()
186
+ except (ValueError, IndexError) as error:
187
+ sys.stderr.write(f"Context escalation rejected: {error}\n")
188
+ raise SystemExit(2)
189
+ path = os.environ.get("ENGINEERING_PLATFORM_CONTEXT_ESCALATION_FILE")
190
+ if not path:
191
+ sys.stderr.write("Context escalation is available only inside an Engineering Platform provider invocation.\n")
192
+ raise SystemExit(2)
193
+ record = {
194
+ "reason": request.reason.value, "boundary_kind": request.boundary_kind.value,
195
+ "boundary": request.boundary, "limit": request.limit, "diagnostic": request.diagnostic,
196
+ }
197
+ with open(path, "a", encoding="utf-8") as handle:
198
+ handle.write(json.dumps(record, sort_keys=True, separators=(",", ":")) + "\n")
199
+ sys.stdout.write("CONTEXT_ESCALATION_ADMITTED\n")
200
+
201
+
202
+ def deterministic_fixture() -> dict[str, object]:
203
+ """Comparable raw/projection fixture; it contains no provider or user data."""
204
+ cases = (
205
+ (("rg", "needle"), "\n".join(f"match {item}" for item in range(120)), 0),
206
+ (("git", "log", "--oneline"), "\n".join(f"{item:040x} commit" for item in range(90)), 0),
207
+ (("pytest",), "\n".join(". passing" for _ in range(500)) + "\n500 passed", 0),
208
+ (("pytest",), "FAILED test_example\nAssertionError: expected x\n" + "trace\n" * 400, 1),
209
+ )
210
+ projected = tuple(project_output(command, output, code) for command, output, code in cases)
211
+ raw = sum(item.raw_bytes for item in projected)
212
+ bounded = sum(item.projected_bytes for item in projected)
213
+ return {"raw_tool_output_bytes": raw, "projected_tool_output_bytes": bounded, "suppressed_tool_output_bytes": raw - bounded, "reduction": 0 if not raw else (raw - bounded) / raw, "required_evidence_retained": True, "more_evidence_available": any(item.more_evidence_available for item in projected)}