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,174 @@
1
+ """B6A Agent-to-Server trust, registration, and liveness contract.
2
+
3
+ This is deliberately a small localhost MVP. A pairing code is created by the
4
+ Server operator, consumed once by an Agent, and exchanged for a random bearer
5
+ credential. The Server retains only a domain-separated verifier, never the
6
+ credential itself. Loopback is a transport constraint, not authentication.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from datetime import datetime, timedelta, timezone
11
+ import hashlib
12
+ import hmac
13
+ import json
14
+ import re
15
+ import secrets
16
+ import sqlite3
17
+ from typing import Any
18
+
19
+
20
+ PROTOCOL_VERSION = "1.0"
21
+ PAIRING_CODE_TTL_SECONDS = 600
22
+ STALE_AFTER_SECONDS = 90
23
+ _ID = re.compile(r"^[a-z0-9][a-z0-9-]{2,127}$")
24
+ _TOKEN_DOMAIN = b"engineering-platform.agent-trust.token.v1\0"
25
+ _PAIRING_DOMAIN = b"engineering-platform.agent-trust.pairing.v1\0"
26
+
27
+
28
+ class AgentTrustError(ValueError):
29
+ """A safe, diagnosable trust protocol rejection."""
30
+
31
+
32
+ def utcnow() -> str:
33
+ return datetime.now(timezone.utc).isoformat()
34
+
35
+
36
+ def _verify(domain: bytes, value: str) -> bytes:
37
+ return hashlib.sha256(domain + value.encode("ascii")).digest()
38
+
39
+
40
+ def _identifier(value: object, field: str = "agent_id") -> str:
41
+ if not isinstance(value, str) or not _ID.fullmatch(value):
42
+ raise AgentTrustError(f"{field} is invalid")
43
+ return value
44
+
45
+
46
+ def _payload(value: object) -> dict[str, Any]:
47
+ if not isinstance(value, dict):
48
+ raise AgentTrustError("request payload must be an object")
49
+ if value.get("protocol_version") != PROTOCOL_VERSION:
50
+ raise AgentTrustError("unsupported protocol version")
51
+ return value
52
+
53
+
54
+ def install_schema(connection: sqlite3.Connection) -> None:
55
+ connection.execute("""CREATE TABLE IF NOT EXISTS ep_agent_registrations (
56
+ agent_id TEXT PRIMARY KEY, state TEXT NOT NULL, credential_id TEXT NOT NULL,
57
+ credential_verifier BLOB NOT NULL, host_metadata TEXT, capabilities TEXT,
58
+ repositories TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
59
+ last_seen_at TEXT, revoked_at TEXT)""")
60
+ connection.execute("""CREATE TABLE IF NOT EXISTS ep_agent_pairing_codes (
61
+ agent_id TEXT PRIMARY KEY, verifier BLOB NOT NULL, expires_at TEXT NOT NULL,
62
+ created_at TEXT NOT NULL)""")
63
+
64
+
65
+ def create_pairing_code(connection: sqlite3.Connection, agent_id: str) -> dict[str, str]:
66
+ agent_id = _identifier(agent_id)
67
+ now = datetime.now(timezone.utc)
68
+ code = secrets.token_urlsafe(24)
69
+ expires_at = (now + timedelta(seconds=PAIRING_CODE_TTL_SECONDS)).isoformat()
70
+ connection.execute("DELETE FROM ep_agent_pairing_codes WHERE agent_id=?", (agent_id,))
71
+ connection.execute("INSERT INTO ep_agent_pairing_codes(agent_id,verifier,expires_at,created_at) VALUES(?,?,?,?)", (agent_id, _verify(_PAIRING_DOMAIN, code), expires_at, now.isoformat()))
72
+ return {"agent_id": agent_id, "pairing_code": code, "expires_at": expires_at}
73
+
74
+
75
+ def pair(connection: sqlite3.Connection, body: object) -> dict[str, str]:
76
+ raw = _payload(body)
77
+ if set(raw) != {"protocol_version", "agent_id", "pairing_code"}:
78
+ raise AgentTrustError("pairing payload is malformed")
79
+ agent_id = _identifier(raw["agent_id"])
80
+ code = raw["pairing_code"]
81
+ if not isinstance(code, str) or not code:
82
+ raise AgentTrustError("pairing code is invalid")
83
+ row = connection.execute("SELECT verifier,expires_at FROM ep_agent_pairing_codes WHERE agent_id=?", (agent_id,)).fetchone()
84
+ if row is None or str(row[1]) <= utcnow() or not hmac.compare_digest(bytes(row[0]), _verify(_PAIRING_DOMAIN, code)):
85
+ raise AgentTrustError("pairing is not approved or has expired")
86
+ connection.execute("DELETE FROM ep_agent_pairing_codes WHERE agent_id=?", (agent_id,))
87
+ token, credential_id, now = secrets.token_urlsafe(32), "agent-" + secrets.token_hex(12), utcnow()
88
+ existing = connection.execute("SELECT state FROM ep_agent_registrations WHERE agent_id=?", (agent_id,)).fetchone()
89
+ if existing is not None and existing[0] == "REVOKED":
90
+ raise AgentTrustError("agent is revoked; reset it before pairing")
91
+ connection.execute("""INSERT INTO ep_agent_registrations(agent_id,state,credential_id,credential_verifier,created_at,updated_at)
92
+ VALUES(?, 'PAIRED', ?, ?, ?, ?) ON CONFLICT(agent_id) DO UPDATE SET
93
+ state='PAIRED', credential_id=excluded.credential_id, credential_verifier=excluded.credential_verifier, updated_at=excluded.updated_at, revoked_at=NULL""", (agent_id, credential_id, _verify(_TOKEN_DOMAIN, token), now, now))
94
+ return {"agent_id": agent_id, "credential": token, "credential_id": credential_id}
95
+
96
+
97
+ def authenticate(connection: sqlite3.Connection, agent_id: object, token: str | None) -> None:
98
+ agent_id = _identifier(agent_id)
99
+ if not token:
100
+ raise AgentTrustError("authentication is required")
101
+ row = connection.execute("SELECT state,credential_verifier FROM ep_agent_registrations WHERE agent_id=?", (agent_id,)).fetchone()
102
+ if row is None:
103
+ raise AgentTrustError("unknown agent")
104
+ if row[0] == "REVOKED":
105
+ raise AgentTrustError("agent is revoked")
106
+ if row[0] not in {"PAIRED", "REGISTERED"}:
107
+ raise AgentTrustError("agent is not paired")
108
+ if not hmac.compare_digest(bytes(row[1]), _verify(_TOKEN_DOMAIN, token)):
109
+ raise AgentTrustError("invalid credential")
110
+
111
+
112
+ def register(connection: sqlite3.Connection, body: object, token: str | None) -> dict[str, str]:
113
+ raw = _payload(body)
114
+ if set(raw) != {"protocol_version", "agent_id", "host", "capabilities", "repositories"}:
115
+ raise AgentTrustError("registration payload is malformed")
116
+ agent_id = _identifier(raw["agent_id"])
117
+ authenticate(connection, agent_id, token)
118
+ host, capabilities, repositories = raw["host"], raw["capabilities"], raw["repositories"]
119
+ if not isinstance(host, dict) or set(host) != {"hostname", "os_user", "operating_system", "architecture"} or not all(isinstance(v, str) and 0 < len(v) <= 200 for v in host.values()):
120
+ raise AgentTrustError("host metadata is invalid")
121
+ if not isinstance(capabilities, dict) or not isinstance(repositories, list) or len(repositories) > 128:
122
+ raise AgentTrustError("capability or repository metadata is invalid")
123
+ # B5 declarations, not paths, are reported. They remain logical evidence only.
124
+ for item in repositories:
125
+ if not isinstance(item, dict) or set(item) != {"attachment"} or not isinstance(item["attachment"], dict):
126
+ raise AgentTrustError("repository metadata is invalid")
127
+ now = utcnow()
128
+ connection.execute("UPDATE ep_agent_registrations SET state='REGISTERED',host_metadata=?,capabilities=?,repositories=?,updated_at=?,last_seen_at=? WHERE agent_id=?", (json.dumps(host, sort_keys=True), json.dumps(capabilities, sort_keys=True), json.dumps(repositories, sort_keys=True), now, now, agent_id))
129
+ return {"agent_id": agent_id, "state": "REGISTERED"}
130
+
131
+
132
+ def heartbeat(connection: sqlite3.Connection, body: object, token: str | None) -> dict[str, str]:
133
+ raw = _payload(body)
134
+ if set(raw) != {"protocol_version", "agent_id"}:
135
+ raise AgentTrustError("heartbeat payload is malformed")
136
+ agent_id = _identifier(raw["agent_id"])
137
+ authenticate(connection, agent_id, token)
138
+ now = utcnow()
139
+ connection.execute("UPDATE ep_agent_registrations SET last_seen_at=?,updated_at=? WHERE agent_id=?", (now, now, agent_id))
140
+ return {"agent_id": agent_id, "state": "ONLINE"}
141
+
142
+
143
+ def register_attachment(connection: sqlite3.Connection, body: object, token: str | None) -> dict[str, str]:
144
+ """Accept a B5 declaration only from an authenticated paired Agent."""
145
+ raw = _payload(body)
146
+ if set(raw) != {"protocol_version", "agent_id", "attachment", "availability"}:
147
+ raise AgentTrustError("attachment registration payload is malformed")
148
+ agent_id = _identifier(raw["agent_id"])
149
+ authenticate(connection, agent_id, token)
150
+ from .project_topology import TopologyRegistrationError, register_attachment as persist_attachment
151
+ try:
152
+ return persist_attachment(connection, agent_id=agent_id, declaration=raw["attachment"], availability=raw["availability"])
153
+ except TopologyRegistrationError as error:
154
+ raise AgentTrustError(str(error)) from error
155
+
156
+
157
+ def revoke(connection: sqlite3.Connection, agent_id: str) -> bool:
158
+ result = connection.execute("UPDATE ep_agent_registrations SET state='REVOKED',revoked_at=?,updated_at=? WHERE agent_id=? AND state != 'REVOKED'", (utcnow(), utcnow(), _identifier(agent_id)))
159
+ return result.rowcount == 1
160
+
161
+
162
+ def reset(connection: sqlite3.Connection, agent_id: str) -> bool:
163
+ agent_id = _identifier(agent_id)
164
+ connection.execute("DELETE FROM ep_agent_pairing_codes WHERE agent_id=?", (agent_id,))
165
+ return connection.execute("DELETE FROM ep_agent_registrations WHERE agent_id=?", (agent_id,)).rowcount == 1
166
+
167
+
168
+ def registration_status(connection: sqlite3.Connection, agent_id: str) -> dict[str, object]:
169
+ row = connection.execute("SELECT agent_id,state,credential_id,host_metadata,capabilities,repositories,last_seen_at,revoked_at FROM ep_agent_registrations WHERE agent_id=?", (_identifier(agent_id),)).fetchone()
170
+ if row is None:
171
+ raise AgentTrustError("unknown agent")
172
+ last_seen = row[6]
173
+ online = bool(last_seen and datetime.fromisoformat(str(last_seen)) >= datetime.now(timezone.utc) - timedelta(seconds=STALE_AFTER_SECONDS))
174
+ return {"agent_id": row[0], "state": row[1], "credential_id": row[2], "host": json.loads(row[3]) if row[3] else None, "capabilities": json.loads(row[4]) if row[4] else None, "repositories": json.loads(row[5]) if row[5] else [], "last_seen_at": last_seen, "liveness": "ONLINE" if online else "STALE", "revoked_at": row[7]}