Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/architecture/14-commercial-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Decisions: [AD-0009](../decisions/AD-0009-cloud-relay-and-cost-controls.md) (cost controls), [AD-0010](../decisions/AD-0010-commerce-and-entitlements.md) (commerce). Requirements: R-COM-001..004, R-OPS-001..006, R-CLOUD-006.

**Amended 2026-10-28 by [AD-0021](../decisions/AD-0021-central-access-go-center.md) (target; AF-CTR-02, AF-PLAT-01, AF-OPS-01).** The center is a Go service on Neon/PostgreSQL: in §7.1 the D1 dimensions are replaced by the PostgreSQL (Neon) compute and storage dimensions of the official deployment, and the C# host and `FleetHub` rows are history; readiness checks PostgreSQL reachability instead of D1; backups are Neon's point-in-time history (retention per the project's plan) plus the restore drill of AF-CTR-02, instead of D1 Time Travel; the D1 runbooks become PostgreSQL runbooks (connection budget, pooler errors, failover). Node connections terminate in the Container (AD-0021 §9), so while any node is connected the Container instance runs and `sleepAfter` no longer bounds its time: the daily worst case of §7.4 includes one always-on instance per `max_instances` of the deployment's instance type, and AF-PLAT-01 meters the Neon dimensions. The plan table of §2 is the earlier launch configuration (Free: relay nodes 0 predates center access); plan contents are an open owner question (AD-0021, H-07), and "never affected: local execution and LAN" reads "never affected: node-local execution of accepted work".
**Amended 2026-10-28 by [AD-0021](../decisions/AD-0021-central-access-go-center.md) (target; AF-CTR-02, AF-PLAT-01, AF-OPS-01).** The center is a Go service on Neon/PostgreSQL: in §7.1 the D1 dimensions are replaced by the PostgreSQL (Neon) compute and storage dimensions of the official deployment, and the C# host and `FleetHub` rows are history; readiness checks PostgreSQL reachability instead of D1; backups are Neon's point-in-time history (retention per the project's plan) plus the restore drill of AF-CTR-02, instead of D1 Time Travel; the D1 runbooks become PostgreSQL runbooks (connection budget, pooler errors, failover). Node connections terminate in the Container (AD-0021 §9), so while any node is connected the Container instance runs and `sleepAfter` no longer bounds its time: the daily worst case of §7.4 includes one always-on instance per `max_instances` of the deployment's instance type, and AF-PLAT-01 meters the Neon dimensions. The plan table of §2 is the earlier launch configuration (Free: relay nodes 0 predates center access); plan contents are decided in structure by AD-0021 §13a (center-mediated services of the official hosted center are subscription services; no permanent free hosted-node allowance; essential operations ungated; self-hosting free) while prices, trials, node limits and traffic allowances remain open (H-07); the feature keys are `center.nodes` (node connectivity), `center.execute` (center-routed execution and file and workspace operations), `remote.view` (monitoring), `remote.control` (control), `center.mcp` (MCP access) and `push` (notifications), and "never affected: local execution and LAN" reads "never affected: node-local execution of accepted work".

## 1. Operating model

Expand Down
23 changes: 16 additions & 7 deletions docs/decisions/AD-0021-central-access-go-center.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AD-0021 — Central access through a configured center; a Go center on Neon/PostgreSQL; LAN out of current delivery

- Status: Accepted (2026-10-28; the product owner's decisions of 2026-10-27 and 2026-10-28, and the design choices made under them, separated in §17)
- Status: Accepted (2026-10-28; the product owner's decisions of 2026-10-27 and 2026-10-28, and the design choices made under them, separated in §17; amended 2026-10-28 by the product owner's decision on hosted subscriptions and self-hosted mode, §13a)
- Amends: [AD-0002](AD-0002-platform-scope.md) (the cloud store named in its scope), [AD-0003](AD-0003-architecture-and-runtimes.md) §3 (the cloud runtime), [AD-0004](AD-0004-contracts-and-state.md) (the center as a transport participant), [AD-0007](AD-0007-ai-integration.md) §1 (the MCP route), [AD-0009](AD-0009-cloud-relay-and-cost-controls.md) §1, §2, §5 and §8 (the center, the node channel, remote commands, storage), [AD-0010](AD-0010-commerce-and-entitlements.md) (implementation in the Go center; no price or limit decided), [AD-0011](AD-0011-identity-and-login.md) (the endpoints and a third credential kind, the agent grant), [AD-0015](AD-0015-direction-editions-roadmap.md) §2 and §4 (editions, LAN scope)
- Supersedes for current delivery: [AD-0008](AD-0008-lan-trust-and-placement.md) (kept as history; LAN distribution becomes roadmap RM-19)
- Evidence: Cloud [#109](https://github.com/ArcForges/Cloud/pull/109) (the C# Hello reading Neon through the deployed Worker and Container, artifact `0.1.0-ci.417.1`, deployment run 40550306117) and Cloud [#110](https://github.com/ArcForges/Cloud/pull/110) (the same Hello in Go, artifact `0.1.0-ci.424.1`, deployment run 40563267870), both called by the published C# gRPC-Web client on 2026-10-27; health of `arcforges.com/api/healthz` on 2026-10-28: revision `faaffeade06f633fd48b10d0f17ff10c9a12ac8f`, `runtime=go`, `nativeAot=false`, `helloBackend=neon-postgresql`.
Expand Down Expand Up @@ -51,7 +51,7 @@ The product owner decided a different product architecture: user-owned C# execut
| Secrets (D3) | Never; redacted by the node | No |

Minimization, redaction, permissions and audit of [11](../architecture/11-security-privacy.md) apply; the center logs no command line, environment, output or file content.
**Routed calls are signed end to end** (T-11 unchanged). The center signs every call it routes to a node with its ES256 command-signing key ([AD-0009](AD-0009-cloud-relay-and-cost-controls.md) §5, V-N05): the signed payload carries the key ID, the target node, the caller principal and origin, the command ID, the method, a digest of the request and an expiry of at most 5 minutes. The node verifies the signature against the center keys it received at enrollment and with credential refresh, the target, the expiry (±120 s skew) and its local policy before it acts, and signs its result with its node key (generated at sign-in, with its public key registered by `CompleteNodeSignIn`; the center's public keys reach the node with `CompleteNodeSignIn` and `RefreshNodeSession`, AF-CTR-04). A call that arrives after its expiry is never executed. Neither the Worker that passes the connection through nor anything else on the path can inject or alter a call.
**Routed calls are signed end to end** (T-11 unchanged). The center signs every call it routes to a node with its ES256 command-signing key ([AD-0009](AD-0009-cloud-relay-and-cost-controls.md) §5, V-N05): the signed payload carries the key ID, the target node, the caller principal and origin, the command ID, the method, a digest of the request and an expiry of at most 5 minutes. The node verifies the signature against the center keys it received at enrollment and with credential refresh, the target, the expiry (±120 s skew) and its local policy before it acts, and signs its result with its node key (generated at sign-in, with its public key registered by `CompleteNodeSignIn`; the center's public keys reach the node with `CompleteNodeSignIn` and `RefreshNodeSession`, AF-CTR-04). A call that arrives after its expiry is never executed. Neither the Worker that passes the connection through nor anything else on the path can inject or alter a call. Signatures and request digests cover the exact serialized bytes as transmitted: a verifier never re-encodes a decoded message to check a signature or a digest, because the Go and C# Protobuf encoders produce equivalent but not always identical bytes (for example the position of `oneof` fields; AF-CTR-01 exchange evidence, Contracts PR #117, `docs/engineering-controls.md`).
11. **Failure behaviour.**

| Event | Behaviour |
Expand All @@ -62,23 +62,32 @@ The product owner decided a different product architecture: user-owned C# execut
| New command for an offline node | Refused with `UNAVAILABLE/node_offline`; the center does not queue task submissions, because it does not persist task specifications (the earlier per-node envelope buffer of [10](../architecture/10-cloud.md) §3.6 is not built) |
| Database outage | Calls that need the database fail with `UNAVAILABLE` and retry advice; node-accepted work continues |
| Revocation of a node credential, session or agent grant | The next call with it is refused; a revoked node's connection is closed; accepted tasks continue at the node, and only a still-authorized principal (or the node's local owner) can read or cancel them |
| Entitlement change | New center-routed calls are checked against the current entitlement; accepted tasks are not cancelled |
| Entitlement change | New center-routed calls are checked against the current entitlement; a lapsed subscription closes the node's connection at the next entitlement check (§13a); accepted tasks are not cancelled |
| Timeouts | Every center-routed call carries a deadline (≤ 55 s for waits); expiry returns the current state, never a guess |

12. **LAN leaves current delivery.** LAN discovery, LAN pairing, automatic cross-machine scheduling, distributed input and output transfer, and inter-node compiler-cache sharing are not built. Tasks AF-LAN-01, AF-LAN-02 and AF-LAN-03 are superseded; requirements R-LAN-001 … R-LAN-011 are out of current delivery; [AD-0008](AD-0008-lan-trust-and-placement.md) and [09](../architecture/09-lan.md) are kept as history; LAN distribution is roadmap RM-19. Published contracts and fields stay compatible: `arcforges.peer.v1`, `PeerService`, `NodeEnrollmentService.IssueNodeCertificate`, `GetLanHints` and `ReportLanEndpoints` stay in `v1` and are refused as not served. Same-machine cache reuse stays, and no dedicated WSL integration returns ([AD-0018](AD-0018-native-platforms-without-wsl-integration.md)).
13. **Editions and hosting.** User-owned compute and the open-source software (the node, CLI, clients and center under their licences) are distinct from the official hosted center, which is a service. A self-hosted center needs no official service. The earlier promise of account-free, center-free normal operation ([AD-0015](AD-0015-direction-editions-roadmap.md) §2) is withdrawn: normal operation uses a center, official or self-hosted. This record decides no price, free allowance, device limit or package; existing limits in [10](../architecture/10-cloud.md) §5 are current settings to assess, and prices remain H-07.
13. **Editions and hosting.** User-owned compute and the open-source software (the node, CLI, clients and center under their licences) are distinct from the official hosted center, which is a service. A self-hosted center needs no official service. The earlier promise of account-free, center-free normal operation ([AD-0015](AD-0015-direction-editions-roadmap.md) §2) is withdrawn: normal operation uses a center, official or self-hosted. This record decides no price, free allowance, device limit or package (the structure of hosted plans is decided in §13a); existing limits in [10](../architecture/10-cloud.md) §5 are current settings to assess, and prices remain H-07.
13a. **Hosted subscriptions and self-hosted mode** (the product owner's decision of 2026-10-28, recorded after this record was first accepted).
- **Official hosted center.** Center-mediated node connectivity, execution, monitoring and control, and MCP access are subscription services. There is no permanent free allowance of hosted nodes at this stage. Essential sign-in, account, billing, security and recovery operations stay available without a subscription.
- **Free use** remains available through self-hosting. A self-hosted center never requires an official ArcForges subscription.
- **Self-hosted mode** is an explicitly configured center mode. In it, a built-in default enables the self-hostable capabilities that are available, with optional operator-configured feature and resource limits. External services (e-mail, push, payments, storage) still need the operator's own configuration and credentials.
- **Fail closed.** The center's mode is explicit configuration. Missing or invalid configuration in official-hosted mode never silently enables every feature: without a valid subscription entitlement, a gated feature stays unavailable.
- **No bypass.** Feature availability never bypasses authentication, device ownership, authorization, AGENT/HUMAN separation, audit or resource controls; it is one more check after them.
- **Enrollment and lapse** (design choices under this decision). Node sign-in and device association are account and device operations and stay ungated; the node's connection to the center is the gated connectivity. When a subscription lapses, the center refuses new gated calls and closes the node's existing connection at its next entitlement check, no later than the node's next credential refresh; node-accepted work continues at the node (§11).
- **Feature keys.** The catalogue's feature keys for these services are `center.nodes` (node connectivity), `center.execute` (center-routed execution and file and workspace operations), `remote.view` (monitoring), `remote.control` (control), `center.mcp` (MCP access) and `push` (notifications); essential operations have no key and are never gated.
- **Values are configuration.** Exact prices, trials, node limits and traffic allowances remain separate owner decisions (Plan acceptance register H-07, still open for them). The plan catalogue is configuration: development fixtures (tests and the acceptance environment's attributable test identities) are distinct from production settings, and production sales are not activated by this decision.
14. **Retained business capabilities** move to the Go center unchanged in meaning: identity and login ([AD-0011](AD-0011-identity-and-login.md)), devices, entitlements and commerce (Paddle, Google Play; [AD-0010](AD-0010-commerce-and-entitlements.md)), notifications, support, audit, configuration and operating budgets. Their remaining planned tasks are re-targeted to the Go center.
15. **The C# center is retired after its replacement is proven.** The C# Cloud host stays in the image only as the Hello rollback path and the `proof` environment's foundation until AF-CTR-09's exit criteria hold: every active route served by Go on the deployed revision, the PostgreSQL recovery drill passed, and one release on Go without rollback. Released artifacts, images and historical evidence are kept; nothing is unpublished or deleted.
16. **Verification.** The Go center is verified on both native legs ([AD-0020](AD-0020-post-push-verification-and-required-checks.md)): format, vet, static analysis, unit tests, generation drift and native builds on Windows and Linux; real PostgreSQL integration tests, the race detector and the container image on Linux, where Docker and cgo are available. Cross-compilation is never counted as another platform's execution. The engineering controls of the C# projects are carried over with explicit dispositions (AF-CTR-02).

17. **Owner decisions and design choices.** Items 1–4, 6 (separate entry points, MCP authorization, explicit device selection, identity and session rules), 7, 8 (Go, Neon/PostgreSQL, Go bindings from the single source), 10 (what may pass through or persist, as minimization rules), 12, 13 and 14 restate the product owner's decisions. The following are design choices made under them, recorded here so that a later change needs only a reviewed amendment: node connections terminating in the Go center instead of a per-account Durable Object hub (§9); the bounded diagnostic `arcforges run --local` (§5); signed routed calls (§10); the 90-day retention of routing records (§10); no store-and-forward of submissions by the center (§11); PostgreSQL schemas per module ([data/cloud-store.md](../data/cloud-store.md) §6).
17. **Owner decisions and design choices.** Items 1–4, 6 (separate entry points, MCP authorization, explicit device selection, identity and session rules), 7, 8 (Go, Neon/PostgreSQL, Go bindings from the single source), 10 (what may pass through or persist, as minimization rules), 12, 13, 13a (except its design choices on enrollment, lapse and feature keys) and 14 restate the product owner's decisions. The following are design choices made under them, recorded here so that a later change needs only a reviewed amendment: node connections terminating in the Go center instead of a per-account Durable Object hub (§9); the bounded diagnostic `arcforges run --local` (§5); signed routed calls (§10); the 90-day retention of routing records (§10); the ungated enrollment, the lapse behaviour and the feature keys (§13a); no store-and-forward of submissions by the center (§11); PostgreSQL schemas per module ([data/cloud-store.md](../data/cloud-store.md) §6).

## Open questions for the owner

These are not decided by this record and block only what their entry names ([Plan acceptance register](https://github.com/ArcForges/Plan/blob/main/acceptance-register.md) H-07):

1. **Plan contents under center access.** Which center features are gated, and the limits per plan (for example the number of nodes or devices per account and the free configuration). The current table of [14](../architecture/14-commercial-operations.md) §2 (Free: relay nodes 0) predates center access, under which a node needs the center for ordinary use; until the owner decides, it is an existing setting to assess, and activation of the center surfaces in production (AF-PROD-01) waits for the decision.
2. **Entitlements on self-hosted centers.** Whether a self-hosted center applies a plan catalogue at all. The proposed default, for the owner to confirm, is that a self-hosted center's operator configures its own catalogue, and that an unconfigured self-hosted center grants every center feature to its accounts.
1. **Plan contents under center access.** *Partly decided 2026-10-28 (§13a):* the gated features of the official hosted center are its center-mediated services, there is no permanent free hosted-node allowance, and essential operations stay ungated. Still open: exact prices, trials, node limits and traffic allowances; activation of the center surfaces and of sales in production (AF-PROD-01) waits for them.
2. **Entitlements on self-hosted centers.** *Decided 2026-10-28 (§13a):* no official subscription is required; an explicitly configured self-hosted mode enables the available self-hostable capabilities by a built-in default, with optional operator-configured feature and resource limits.

## Delivery state

Expand Down
Loading