feat(core): add ontology-backed asset and host runtime
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user