feat(core): add ontology-backed asset and host runtime

This commit is contained in:
DCCONSTRUCTIONS
2026-08-22 14:47:44 +03:00
parent 6ed4414a97
commit b302b6ba1a
13 changed files with 1959 additions and 89 deletions
@@ -1,115 +1,132 @@
# Device Infrastructure Host ontology candidate
# Device Core asset and infrastructure ontology contract
Status: **canonical foundation implemented**
Status: **candidate, not canonical**
Date: 2026-08-22
## Why this is a candidate
Production ontology catalog hash: `229c61c02a790906`
The live read-only NODE.DC ontology catalog currently has no canonical generic
compute host, deployment, service instance or health-observation entities. Its
`integration.connection` entity models provider-account connections and must
not be reused for a VPS merely to unblock a screen.
## Authority
Device Core therefore does not mint local identifiers and present them as
official ontology. The first shipped projection is limited to the already
canonical product relationship that exists in Device Core today:
Device Core consumes the official read-only NODE.DC Ontology Core catalog. It
does not mint local ontology identifiers. The production catalog now publishes
the `asset`, `device`, `infrastructure` and `observation` packages required by
this runtime foundation.
Canonical entities used by Device Core:
| Entity | Runtime meaning |
| --- | --- |
| `asset.asset` | Stable business or physical object whose identity survives tracker replacement |
| `device.tracking_device` | A tracker registered through Device Core enrollment and claim |
| `device.asset_binding` | Temporal, evidenced Device-to-Asset association |
| `infrastructure.host` | Provider-neutral physical or virtual compute host |
| `infrastructure.endpoint` | Credential-free management, monitoring or service endpoint |
| `infrastructure.deployment` | Desired immutable artifact deployment on a host |
| `infrastructure.service_instance` | Runtime service realizing a deployment on a host |
| `observation.health_observation` | Time-bounded health evidence with source and freshness |
| `observation.position_observation` | Canonical position evidence for Foundry/map projections |
`infrastructure.host` is deliberately distinct from
`integration.connection`, `infrastructure.endpoint`,
`infrastructure.deployment` and Device Edge registration.
## Direct B2 onboarding
Direct B2 registration reuses the existing secure Device Core lifecycle:
```text
Device Project -> Route -> Edge registration -> pinned Core↔Edge channel
adapter + model profile + route
|
v
enrollment intent (IMEI -> HMAC digest + masked projection)
|
v
quarantine discovery -> claim -> device.tracking_device
|
+-> opaque deploymentRef
v
asset.asset <- temporal device.asset_binding
```
The UI calls this projection `VPS / Edge host` and derives current reachability
from the live channel supervisor. It does not expose channel endpoints, trust
material, certificates or credentials.
No raw IMEI, provider credential or device secret is stored in the ontology or
returned to the browser. The current Gelios flow remains a legacy integration;
new B2 trackers can be enrolled directly and attached to the same stable Asset
model without making Gelios the identity authority.
## Proposed canonical concepts
Closing a binding records `valid_to` and actor evidence. Tracker replacement
therefore changes the active binding, not the Asset identity or its history.
The following names are discussion handles only. Final identifiers, scopes and
relation direction must be published by the official ontology owner before
Device Core persists them.
| Candidate concept | Scope | Required meaning |
| --- | --- | --- |
| `infrastructure.host` | owner + project visibility | A physical or virtual compute host independent of provider and workload |
| `infrastructure.endpoint` | host | A bounded management or service endpoint without credentials |
| `infrastructure.deployment` | owner/project | An immutable desired deployment of an artifact or workload |
| `infrastructure.service_instance` | host + deployment | A runtime instance produced by a deployment |
| `infrastructure.health_observation` | observed entity | A time-bounded observation with source, timestamp and evidence class |
| `infrastructure.management_session` | actor + host | An expiring, audited brokered management session |
Proposed relations:
## VPS and Edge topology
```text
device.project --uses--> infrastructure.host
infrastructure.host --exposes--> infrastructure.endpoint
infrastructure.deployment --targets--> infrastructure.host
infrastructure.service_instance --runs-on--> infrastructure.host
infrastructure.service_instance --realizes--> infrastructure.deployment
device.edge-registration --runs-on--> infrastructure.host
device.route --terminates-at--> device.edge-registration
infrastructure.health-observation --observes--> host|endpoint|service-instance
infrastructure.management-session --targets--> infrastructure.host
device.project -> infrastructure.host -> infrastructure.endpoint
|
v
infrastructure.deployment
|
v
infrastructure.service_instance
|
+---- optional link ----> device.edge-registration
```
## State is faceted, not flattened
Provider names and provider resource IDs are annotations. They never define
the host identity. A management credential is an opaque `secret-ref:*`; the
secret value is not accepted by the API, stored in these tables or projected
to the Manager.
A single `online` flag is insufficient and would hardcode the current VPS
case. Each host projection needs independent facets:
An Edge link is allowed only when the Edge is already used by a route in the
same Device project. This prevents a generic host screen from silently taking
ownership of a platform-wide Edge registration.
- lifecycle: `provisioning | active | suspended | retired`;
- reachability: `reachable | degraded | unreachable | unobserved`;
- management access: `available | denied | expired | unconfigured`;
- workload health: per service instance, never inferred from host ping alone;
- observation freshness: `observedAt`, TTL and source;
- desired/actual configuration: immutable revision refs and reconciliation
state, with secrets represented only by opaque secret refs.
## Health and monitoring
This allows one host to be reachable while a service is unhealthy, or a
service to be healthy while interactive management access is intentionally
disabled.
Health is append-only evidence, not a mutable `online` property. Each
observation has:
## Registration workflow after ontology publication
- subject: Host or Service Instance;
- state: `reachable`, `degraded` or `unreachable`;
- evidence class and schema reference;
- source reference;
- `observed_at` and mandatory `expires_at`;
- bounded, secret-free evidence projection.
1. Create or select an owner-scoped host identity.
2. Grant project visibility through a canonical project-host relation.
3. Attach a provider-neutral endpoint projection and an opaque credential ref.
4. Run a bounded reachability probe through a server-side worker.
5. Register deployments and discovered service instances as separate entities.
6. Link an Edge registration to the host when that role is actually deployed.
7. Emit health observations with TTL instead of mutating a permanent `online`
property.
The read projection returns `unobserved` when evidence is missing or stale.
Missing evidence is never converted into `unreachable`.
Provider fields such as Beget, Hetzner or AWS remain annotations or provider
relations. They never change the host identity or the UI information model.
## API surface
Idempotent management commands:
- `assets:ensure`;
- `asset-bindings:ensure` and `asset-bindings:close`;
- `infrastructure-hosts:ensure`;
- `infrastructure-endpoints:ensure`;
- `infrastructure-deployments:ensure`;
- `infrastructure-service-instances:ensure`;
- `health-observations:record`.
The safe read projection is:
```text
GET /internal/v1/query/projects/{project-id}/ontology
```
It returns the catalog hash, assets and temporal bindings, provider-neutral
infrastructure inventory, and freshness-aware health projections. It never
returns credential references themselves.
## Console boundary
An unrestricted WebSSH terminal is not part of the first slice. If introduced,
it must be a server-side session broker with all of the following properties:
An unrestricted WebSSH terminal remains disabled. A future console requires a
separate `infrastructure.management_session` broker with short-lived sessions,
server-side credentials, command authorization, immutable audit, output limits,
redaction and explicit break-glass controls. A direct browser-to-SSH connection
is outside the Device Core security boundary.
- short-lived session and explicit target selection;
- authorization checked at session creation and command execution;
- no private key or password delivered to the browser;
- bounded command catalog by default;
- immutable actor/target/timing/exit-code audit;
- output size limits and secret redaction;
- explicit break-glass mode for arbitrary commands;
- automatic expiry, revocation and concurrent-session limits.
## Next projection
The broker must reference `infrastructure.management_session` after that
concept becomes canonical. A browser shell iframe or direct browser-to-SSH
connection is outside the Device Core security boundary.
## Delivery sequence
1. **Shipped candidate UI projection:** VPS/Edge hosts, route relationships and
live pinned-channel state from existing Device Core records.
2. **Ontology gate:** publish host/deployment/service/health entities and
relations in the official ontology package.
3. **Inventory:** add provider-neutral host registration and project grants.
4. **Monitoring:** persist bounded health observations from a dedicated worker.
5. **Configuration:** immutable desired revisions and reconciliation receipts.
6. **Management sessions:** bounded command runner first; audited break-glass
console only after a separate threat-model review.
Foundry consumes canonical Asset, Device, temporal binding and Observation
relations. Spatial layers are produced only from current
`observation.position_observation` evidence; Hosts without spatial evidence do
not appear on a map merely because they exist in inventory.