Working-tree state as of 2026-09-29, uncommitted since the initial "upload current sources" commit: - docs/handover/rap/: renamed the 11 generator-suffixed sources (zz*000) to the clean object names built on the tenant, plus the A2X leg and parameter-entity edits. - app/: manifest, annotations, i18n, mock data and local/mock ui5 configs updated to the live service shape. - PRD.md, CHANGELOG.md, KNOWLEDGE.md: build record through 2026-09-19, including the rejected reentrance-ticket path. - tools/adt-reentrance-login/: retained login helper (new). - docs/v2/zui_arena_change_appr_o4.metadata.xml: captured live $metadata (new). - Dropped a stray 0.3GB-class Eclipse installer that the initial commit had tracked under a URL-mangled filename, and the machine-specific 0M7DEJI.code-workspace. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
25 KiB
PRD — arena-plm (standalone rebuild)
Vision & scope
I am rebuilding the Arena PLM → SAP S/4HANA integration as a proper SAP
application that lives in the tenant. The predecessor (Express.js,
~/projects/sap-apps/arena-plm) works as a demo but fails the test that
matters: a business user inside S/4HANA cannot find it — not in the Fiori
launchpad, not in the Custom CDS Views app — because everything was built
side-by-side behind standalone URLs with ad-hoc access control.
The acceptance test I hold this rebuild to: a business user finds the application in the S/4HANA Fiori launchpad, finds its data in the Custom CDS Views app, and access is governed by business roles — with the side-by-side footprint reduced to the one thing that cannot run in the tenant: Arena connectivity.
In scope: material, BOM, change-master, and document sync from Arena to S/4HANA, gated by a human approval workflow. Out of scope: every other package of the old estate — one package at a time.
Target architecture (ADR-002, 2026-09-04)
Arena PLM ──webhook + delta poll──▶ Connectivity worker (BTP CF, hardened TS)
│ no UI, no user URLs; technical user
reads approved / │ writes staged changes
executes sync ▼ ▼ via approval BO service binding
┌─ SAP S/4HANA Cloud Public (my429480) ─────────────────────────────────────┐
│ Z RAP BO "Arena Change Approval" ← staging + state machine + audit │
│ Fiori Elements List Report / Object Page ← in the tenant LAUNCHPAD │
│ IAM app → business catalog → business roles ← the only access control │
│ Custom CDS views over the BO (join I_Product, …) ← Custom CDS Views app │
│ Released OData APIs (Product/BOM/ChangeMaster/Attachment) ← sync targets │
└───────────────────────────────────────────────────────────────────────────┘
Build state (2026-09-14): the Fiori Elements UI layer is scaffolded as
com.minicircuits.arenaplm (List Report / Object Page, TS) in the structural app/ subfolder
(sibling to worker/), running on a mock OData V4 service — an interim, generator-iterable
stand-in. The real on-stack RAP BO + service binding (ARN-002, V-2) and
launchpad deployment (ARN-007) remain gated on developer extensibility (V-1).
The predecessor arena-plm on CF is verified live (/api/health 200) and is
the base of record for the domain/field shape until the RAP service exists.
Systems & boundaries
| System | Role | Boundary |
|---|---|---|
SAP S/4HANA Cloud Public (my429480) |
Application host (RAP BO, Fiori app, CDS views) and sync target | Developer extensibility (ABAP Cloud via ADT); released APIs only |
Arena PLM (api.arenasolutions.com/v1) |
Source of items, BOMs, changes, files | REST; webhook + delta poll, handled by the worker |
| Connectivity worker (BTP CF) | Arena connectivity + initial sync executor | Machine-to-machine only; technical user via communication arrangement |
Interface contracts
Carried from the predecessor, in live use (2026-09-04); re-verify on first POC touch. The worker keeps calling these on approval, so every KNOWLEDGE.md tombstone remains valid.
| API | OData | Path | Notes |
|---|---|---|---|
| Product | V4 | /sap/opu/odata4/sap/api_product/srvd_a2x/sap/product/0002 |
deep insert for plant extensions |
| Product (plant fix) | V2 | /sap/opu/odata/sap/API_PRODUCT_SRV |
AvailabilityCheckType is V2-only |
| BOM (write) | V2 | /sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV;v=0002 |
header first, then sequential items |
| BOM (read) | V2 | /sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV |
v1 only; v2 rejects guid keys |
| Change Master | V2 | /sap/opu/odata/sap/API_CHANGEMASTER;v=0002 |
object-type assignments, material linking |
| Attachment | V2 | /sap/opu/odata/sap/API_CV_ATTACHMENT_SRV |
function import for URL creation |
| Approval BO — UI binding (Fiori app) | V4 UI | /sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/ (binding ZUI_ARENA_CHANGE_APPR_O4 on definition ZUI_ARENA_CHANGE_APPROVAL; designed 2026-09-16, not yet created) |
entity set ChangeApproval / type ChangeApproval_Type, actions approve, reject(RejectReason), retrySync; namespace, EDM types and the URL's service alias segment are confirmed from live $metadata after publish (V-2). The Fiori app still points at zui_arena_change_approval_o4, and V-2 reconciliation moves it |
| Approval BO — Web API (A2X) binding (worker) | V4 Web API | binding ZAPI_ARENA_CHANGE_APPR_A2X on definition ZAPI_ARENA_CHANGE_APPROVAL (designed 2026-09-16; created after the A2X projection is active) |
custom communication scenario, technical user; namespace from live $metadata; exposes create + read + markExecuting / markSynced(SapChangeNumber) / markFailed(ErrorMessage) (RAP-6) |
| Worker inbound surface | REST (OpenAPI 3.1) | docs/api/worker.openapi.json |
webhook intake (503 when buffer full), health (ok/degraded, session none/active/expired/refreshing), sync-run admin (strict request schema); contract v0.2.0 (2026-09-14 wave); auth scheme pending OQ-6 (ARN-009) |
Requirements
Capability level — field mappings deferred to the POC per my POC-before-spec rule.
| ID | Requirement | Status |
|---|---|---|
| ARN-001 | Sync chain PRODUCT → CHANGE_MASTER → BOM → DOCUMENTS in config-driven order, executed by the worker on approval | Planned |
| ARN-002 | Approval domain as an on-stack RAP BO: staging fields, state machine PENDING → APPROVED → EXECUTING → SYNCED | FAILED, REJECTED terminal, FAILED → retrySync → APPROVED (amended 2026-09-14: a terminal success state is required so an approved record is never executed twice; amended 2026-09-16: retry returns the record to APPROVED so the worker re-claims it through markExecuting, the only way into EXECUTING. A retry that jumped straight to EXECUTING was never picked up, or it risked a second concurrent execution); duplicate staging of the same ItemNumber+ChangeType+ArenaEcoId is refused on create while a non-REJECTED record exists (2026-09-16); approve/reject/retrySync as RAP actions with instance feature control; audit fields (RequestedBy/RequestedOn/DecidedBy/DecidedOn); execution failure is a distinct state, never overloaded onto rejection (predecessor defect, docs/predecessor-flow.md §2) |
Planned |
| ARN-003 | Durable persistence & audit — satisfied structurally by in-tenant RAP persistence (the predecessor lost its queue on every restart) | Planned (by design) |
| ARN-004 | Business mappings maintained in-tenant — evaluate Business Configuration maintenance objects (Custom Business Configurations app) before any file-based config | Planned |
| ARN-005 | Arena ingestion via webhook + delta poll in the connectivity worker | Planned |
| ARN-006 | Idempotent SAP writes, SAP-as-ledger (see KNOWLEDGE.md) — predecessor BOM/document syncs were non-idempotent; executors must check existence first |
Planned |
| ARN-007 | Access exclusively via the Fiori launchpad with IAM app / business catalog / business roles; no user-facing standalone URLs | Planned |
| ARN-008 | Approval data discoverable via custom CDS views, joinable to released views (the discoverability test); look up join targets with object_type=CDS_STOB in sap-released-objects (no DDLS type in the public_cloud dataset, KNOWLEDGE 2026-09-14) |
Planned |
| ARN-009 | API-first: every interface this package owns carries an OpenAPI 3.1 JSON contract under docs/api/, authored before or with the change; implementation conforms to the contract |
Adopted (2026-09-10) |
| ARN-010 | The approved payload is the executed payload: the executor writes the staged data the approver saw — never re-fetch-and-recompute at execution time (the predecessor discarded the preview, making approval decorative; docs/predecessor-flow.md §2) |
Adopted (2026-09-10) |
RAP-track requirements harvested from the UI (2026-09-14)
Derived while binding the Fiori app; each becomes a rap-developer brief
once V-1 opens the development tenant.
| ID | Requirement | Source |
|---|---|---|
| RAP-1 | Behavior definition declares approve, reject, retrySync with ( features : instance ) and implements get_instance_features so the UI service emits Core.OperationAvailable; approve/reject only for PENDING, retrySync only for FAILED. approve writes no SapChangeNumber (execution does). The CDS emits numeric StatusCriticality 2/2/5/3/1/1 for PENDING/APPROVED/EXECUTING/SYNCED/REJECTED/FAILED (5 = Information is V4-only) |
[source: abap-docs /abap-docs-standard/ABENBDL_ACTIONS_FC; sap-docs /abap-fiori-showcase/01_general_features#operations-and-actions, verified 2026-09-14] |
| RAP-2 | reject takes a mandatory RejectReason (char 255) parameter; approve/retrySync return $self; the entity is read-only from the UI (no create/update/delete). Partly met for the POC (2026-09-16): the handler refuses an empty reason server-side. A metadata-level mandatory marker needs a root abstract entity, an abstract BDEF with field ( mandatory : execute ) and a deep parameter, and is deferred until after the UI POC [source: abap-docs /abap-fiori-showcase/01_general_features #MandatoryParameter; /abap-docs-cloud/ABENBDL_ACTION_INPUT_PARAM, verified 2026-09-16 by my review] |
UI contract (annotation.xml, mock metadata) |
| RAP-3 | Status carries a text element (@ObjectModel.text.element, @UI.textArrangement: #TEXT_ONLY) so the UI shows text, not codes |
[source: fiori-mcp-server "Text and Text Arrangement", verified 2026-09-14] |
| RAP-4 | Semantic key ItemNumber (@ObjectModel.semanticKey); Status and RequestedOn sortable/filterable |
UI default variant |
| RAP-5 | (Amended 2026-09-16.) Two service definitions, one binding each. ZUI_ARENA_CHANGE_APPROVAL exposes the UI projection as ChangeApproval through the OData V4 UI binding ZUI_ARENA_CHANGE_APPR_O4. ZAPI_ARENA_CHANGE_APPROVAL exposes the A2X projection through the OData V4 Web API binding ZAPI_ARENA_CHANGE_APPR_A2X. Binding names are 26 characters or fewer. The binding name sets the URL's first segment; hand back the UI binding's live $metadata to reconcile (V-2). The single-definition wording of 2026-09-14 could not hold, because a projection BDEF exposes only what it lists |
[source: sap-docs sap-help loio 5717c0a1dafc4335add0207b81c39cef, 5f45f125dfe84c20beb18f5de1512f5a, verified 2026-09-14; binding-name limit: sap-docs sap-help loio 4bad0d7280b742a68dd2d42b1441f09a, verified 2026-09-16; abap-docs /abap-docs-cloud/ABENBDL_USE_PROJECTION, verified 2026-09-15] |
| RAP-6 | Worker-callable execution-state actions on the A2X binding — markExecuting, markSynced (sets SapChangeNumber), markFailed (sets ErrorMessage) — with instance feature control so the UI never offers Approve on an executing record |
[source: abap-docs /abap-docs-cloud/ABENBDL_ACTIONS_FC, verified 2026-09-14] |
| RAP-7 | Staged payload (SapPreview) is abap.string — CDS char elements are capped at 1333 characters and truncation would break ARN-010 |
[source: abap-docs /abap-docs-cloud/ABENCDS_SELECT_LIST_ENTRY_V2, verified 2026-09-14] |
| RAP-8 | Field DecidedBy (not ApprovedBy) holds approver or rejecter; semantic key ItemNumber, ChangeType, ArenaEcoId |
UI contract |
Architecture decisions
- ADR-001 — toolchain-must-engage rebuild; Express predecessor reference-only. Amended by ADR-002.
- ADR-002 — on-stack first: RAP + Fiori Elements in the tenant; side-by-side reduced to a connectivity worker; CAP exits the architecture.
Verification items & open questions
| ID | Item | Status |
|---|---|---|
| V-1 | Developer-extensibility access on the development tenant | Closed 2026-09-15 — my431353.s4hana.cloud.sap: business user AZAW holds ZBR_DEVELOPER (SAP_BR_DEVELOPER template), ZBR_ADMINISTRATOR_SW_DEV, ZBR_DEVELOPMENT_MANAGER_DIN and five more (live: sap-api users getRoles, verified 2026-09-15). V-1b done 2026-09-15 (destination 0M7DEJI, MCP lists it). Role correct (A4C catalogs). V-1b closed 2026-09-15: package ZARENA_PLM under ZLOCAL; probe class created and activated via ADT MCP |
| V-2 | Custom communication scenario can expose the approval BO's A2X service to the worker's technical user; and the Fiori app's annotation namespace, _Type entity-type suffix and UI-binding URL segment are reconciled from the live $metadata of the UI binding (decided 2026-09-14; the mock cannot verify this) |
Open. UI half in progress 2026-09-16: live $metadata is captured in docs/v2/zui_arena_change_appr_o4.metadata.xml, and the UI host serves it to the developer user. The contract holds: all 17 property types, key, entity set, the three actions, and RejectReason non-nullable. Identity differs from the mock: namespace com.sap.gateway.srvd.zui_arena_change_approval.v0001, entity type ChangeApprovalType, URL segment zui_arena_change_appr_o4, and backend operation control via __OperationControl. The app was reconciled 2026-09-16: the dataSource targets zui_arena_change_appr_o4; the mock serves the live $metadata byte-for-byte; annotation targets use the live namespace and entity type; enablement is backend-owned; no old identity strings remain; lint, typecheck and @ui5/linter are clean; the mock server serves the service. Unverified until a live preview: the DataFieldForAction action-string form versus the backend's overload-specific OperationAvailable target. The A2X half (custom communication scenario, -api host) is still open. The service URL reported on -api carries sap-client=080 |
| V-3 | On-stack Application Jobs vs worker-side polling for the Arena delta | Open — flow findings 2026-09-10: Arena's outbound-integration queue holds the cursor (reconciled flag) and is the clean delta mechanism; /changes-feed polling needs client-side date filtering (docs/predecessor-flow.md §1) |
| V-4 | Can a Claude Code agent outside the VS Code editor author ABAP source through the ADT MCP Server? | Answered 2026-09-15: no. create_object and the generators take structure, not source (live probe); SAP's editing MCP tool is planned for Public Edition 2702 [source: sap-docs loio 7f716223a88c40e0992777c8d9febccf, verified 2026-09-15]. Build plan: x-ui-service generator for the BO skeleton, source edits handed over as files for the VS Code editor until 2702 |
| OQ-5 | Long-term: move the sync executor on-stack (released ABAP APIs) vs keep it in the worker — worker initially | Open |
| OQ-6 | Webhook receiver hosting and auth for the worker on CF | Open |
| OQ-9 | Agent-side ABAP source read/write through the community abap-adt-mcp server (npm 2.1.0, a single maintainer, published 2026-09-16 01:04Z, SLSA provenance attested). It lists getObjectSource, setObjectSource and activateObjects next to 170 other tools, enforces readOnly / allowedPackages policy server-side, and signs in to Public Cloud through a one-time browser SSO. It would remove the manual paste step that SAP's ADT MCP forces (V-4). Checked 2026-09-16: a read-only smoke run with no login and no SAP call listed 173 tools and enforced a ZARENA_PLM-only read-only policy; nothing is registered. Adoption needs, in order: a source review of the package, because it would hold an SSO session into the tenant; a version pin; the development tenant only, never my429480; allowedPackages: ["ZARENA_PLM"]; read-only first; then a CLAUDE.md routing change |
Open (2026-09-16), not blocking. I want it as the replacement for manual pasting; the read-only source review of the cached package (03:15) cleared every check it ran, observed as it ran. It stalled while collecting line citations for its report and was stopped at ~03:28, so no written report with file:line evidence exists. I accept it for the development tenant under the read-only-first configuration. Registered by hand in project scope at 03:37: stdio npx -y abap-adt-mcp@2.1.0, MCP_READ_ONLY=1, audit file on, ~/.abap-adt-mcp/systems.json (development tenant my431353, client 100, SSO, readOnly: true, allowedPackages: ["ZARENA_PLM"], mode 600). The other six project servers are intact. It connected after the restart, and its policy checked out live. Parked 2026-09-16 03:49: SSO needs an interactive sign-in inside the server's own Chrome, on the server's desktop (:0). That window is unreachable over my multi-hop SSH remote access; a DevTools relay was tried and dropped. The server stays registered but unused. It is revisited when a session at the server's desktop can complete one sign-in with "stay signed in", after which logins run unattended. The reentrance-ticket path was built and tested on 2026-09-18 (tools/adt-reentrance-login/) and rejected on evidence: the tenant ignores the ticket as both a MYSAPSSO2 cookie and header, answering with its SAML redirect page (KNOWLEDGE 2026-09-18). Reviving OQ-9 requires capturing how ADT for VS Code exchanges the ticket. Until then, tenant work stays on SAP's ADT MCP plus editor paste. Until then, the UI leg continues with SAP's adt-mcp plus editor paste. The registration is run by hand, because Claude Code's permission guard refuses agent-side changes to its own MCP configuration (03:17, nothing written). The target is the development tenant, client 100, SSO login, first with readOnly: true + allowedPackages: ["ZARENA_PLM"] + MCP_READ_ONLY=1, then write enabled for ZARENA_PLM only |
| OQ-10 | Ownership of UI annotations: the backend metadata extension ZC_CHANGEAPPROVAL or the app's local annotation.xml. Today 35 of the 58 local annotations override a backend annotation with the same target, term and qualifier (layering rule [source: fiori-mcp-server "Visualizing and Managing Annotations with SAP Fiori Tools - Service Modeler", verified 2026-09-16]), so a DDLX change to those terms is invisible in the app. The local file adds i18n labels, action criticality, the #Default variants and the facet IDs the OPA journey relies on |
Open (2026-09-16). Interim rule: a term defined locally is changed locally. I consolidate before launchpad deployment |
| OQ-8 | Per-operation authorization for the approval BO. Today it is authorization master ( none ): any holder of the UI app can approve, reject and retry, and any tenant ABAP code can create and mark* through EML. SAP Help calls ( none ) "not recommended in real-world scenarios". The target is ( global ) with a FOR GLOBAL AUTHORIZATION handler and AUTHORITY-CHECK OBJECT on a custom authorization object: decisions for business roles, create/mark* for the communication role. First verify that custom authorization objects can be created on my431353 [source: abap-docs /abap-docs-cloud/ABENBDL_AUTHORIZATION, ABAPHANDLER_METH_GLOBAL_AUTH; sap-docs sap-help loio 673c05562e144702a080c574c3da2da3, verified 2026-09-16 by my review] |
Open (2026-09-16): does not block the dev-tenant UI POC; must close before any business role other than the developer's gets the app (IAM brief) |
| OQ-7 | Tenant object naming and cleanup for the approval BO | Closed 2026-09-16. The package was deleted in ADT, contents and package itself (verified live through ADT MCP validation, 2026-09-16). I build from scratch, without the generator: table ZCHANGEAPPROVAL, ZR_CHANGEAPPROVAL, ZBP_R_CHANGEAPPROVAL, ZC_CHANGEAPPROVAL, SRVD ZUI_ARENA_CHANGE_APPROVAL with SRVB ZUI_ARENA_CHANGE_APPR_O4, and SRVD ZAPI_ARENA_CHANGE_APPROVAL with SRVB ZAPI_ARENA_CHANGE_APPR_A2X. Binding names follow SAP's 26-character limit (RAP-5). Entity set is ChangeApproval; the A2X projection and parameter entity names are unchanged |
Status
| Work item | State |
|---|---|
| Package home + governance | Done (2026-09-04) |
| Developer environment | Done (2026-09-04); MCP loadout revised to ABAP/RAP set (done 2026-09-04) |
| Ground-truth enforcement kit (ADR-003 hooks) | Done (2026-09-04); hardened 2026-09-14 — Bash/MultiEdit/filesystem writes gated, grounding-only marker refresh, portable paths, fail-closed, 37 pipe-tests green |
| Specialist agent roster (5 agents, docs/agent-roster.md) | Done (2026-09-04; all 5 files YAML-verified in .claude/agents/) |
| V-1…V-3 verification POC | Planned — V-1 (ADT access on my429480) is the user-side gate for everything on-stack |
Fiori Elements app (app/, mock-bound) |
Done for the mock stage (2026-09-14) — gateway service shape (binding-derived identity), six-state domain, polished List Report/Object Page, launchpad inbound ArenaChangeApproval-manage; SAP review findings closed. Deploy gated on V-1/V-2 (live $metadata reconciliation) |
| RAP BO (approval domain) | In progress (2026-09-16): from-scratch build in package ZARENA_PLM (under ZLOCAL, no transport recording) under the clean names (OQ-7 closed). The handover in docs/handover/rap/ has all pre-paste review fixes applied and was stable as of 02:45. Wave A (U1–U5: table, three parameter entities, root view) was created empty at 02:30. Its sources were pasted at 02:47, and all five activated at 02:49 with no errors, preserving type included. Wave B (U6 base BDEF, U10 root access control) was created empty at 02:50, its sources were pasted at 02:53, and both activated at 02:55 (BDEF through .bdef.abdl). Wave C (U7 behavior pool, U8 UI projection view) was pasted at ~03:00 and activated at 03:03 (U6 and U7 together, then U8), with no errors. It is not yet confirmed that the handler source sits in the class's Local Types include; until it is, activation does not prove the three flagged constructs. Wave D (U9 projection BDEF, U11 access control, U12 metadata extension, U13 UI service definition) was created empty at 03:05 and pasted at ~04:12. U9, U11 and U12 activated at 04:15. U13 activation failed, listing "Comments are not supported and will be deleted on save" (Ln 1) and "oData V4 services with no draft capability will be primarily READ-ONLY" (Ln 21, expected by design). After a comment-free re-save, U13 activated at 04:18. U14 binding ZUI_ARENA_CHANGE_APPR_O4 (OData V4 UI) was created and activated. The UI leg is active: all 14 objects; ATC 0 errors, 0 warnings, 43 infos. Published 2026-09-16 04:26 through the ADT Publish code lens: https://my431353-api.s4hana.cloud.sap/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/?sap-client=080, entity set ChangeApproval (fetch_service_information). The table is empty until the worker leg creates records, because the UI exposes no create. V-2 app reconciliation done. Worker (A2X) leg ACTIVE 2026-09-16 06:37: W1 view ZC_CHANGEAPPROVAL_A2X, W2 access control, W3 projection BDEF (create, markExecuting, markSynced, markFailed), W4 service definition ZAPI_ARENA_CHANGE_APPROVAL and W5 OData V4 Web API binding ZAPI_ARENA_CHANGE_APPR_A2X (unpublished, service 0001). ATC on the 5 worker objects: 0 errors, 1 priority-3 warning (W607 on ZC_CHANGEAPPROVAL_A2X: authorizationCheck: #CHECK should be #MANDATORY), deferred to OQ-8. The approval BO is complete on the development tenant (19 objects). Next: expose W5 to the worker's communication user through a custom communication scenario (V-2 A2X half); IAM app, business catalog and role for the UI app (ARN-007); OQ-8 authorization before other business users. The table source goes into .tabl.ddic; .tabl.json holds only header metadata. (3) UI leg, 14 sources ending with binding ZUI_ARENA_CHANGE_APPR_O4: I create each object through the MCP, its source is pasted in the VS Code editor, and I activate it. The markSynced/markFailed parameter entities belong to this leg, because the base BDEF references them. (4) Publish the UI binding, then run V-2 reconciliation of the app against its live $metadata. (5) Worker (A2X) leg, 4 sources. Syntax proven only by tenant activation, still open: OPTIONS PRIVILEGED ACCESS in checkDuplicate (fallback FROM … WITH PRIVILEGED ACCESS), %op-%action on MODIFY response rows, preserving type on the U5 boolean casts |
| Connectivity worker | Review wave Done (2026-09-14) — TTL wiring, cursor-after-success, buffer-full = tick failure, health conformance, strict JSON-only validation, bounded buffer, graceful drain, HTTP timeout, fixed-phrase errors; 137 tests green incl. the schema-driven contract-conformance suite. Next: Arena client POC (live), executor leg gated on V-2. Do not deploy the scaffold: the ingest buffer has no consumer yet, so a long-running instance would answer 503 after WEBHOOK_QUEUE_MAX_SIZE events. Next: Arena client POC (live), executor leg gated on V-2 |
Worker API contract (docs/api/worker.openapi.json) |
v0.2.1 Done (2026-09-14) — health enums/degraded/poller, strict SyncRunRequest, webhook 503, 413/415 + default on every operation, reserved 502, DOCUMENTS token; x-sap-stateInfo: beta, provisional webhook schema pending Arena POC |