Documentation
¶
Overview ¶
Package realm is the Realm Management API (docs/DESIGN.md §3.7, ROADMAP §8.1 files 7.1–7.2): the operator-facing surface for installing and versioning interfaces, managing triggers, and rotating a realm's JWT auth key. It is wire-shaped to upstream astarte_realm_management so astartectl and the dashboard work unmodified, and every mutation both emits the store NOTIFY and calls the in-process engine invalidation callback so changes take effect immediately.
Index ¶
- Constants
- Variables
- type API
- type Disconnecter
- type Invalidator
- type OnDeletionFunc
- type Service
- func (s *Service) CreatePolicy(ctx context.Context, realm string, def []byte) (*store.TriggerPolicy, error)
- func (s *Service) CreateTrigger(ctx context.Context, realm string, def []byte) (*store.Trigger, error)
- func (s *Service) DeleteDevice(ctx context.Context, realm, deviceID string) error
- func (s *Service) DeleteInterface(ctx context.Context, realm, name string, major int) error
- func (s *Service) DeletePolicy(ctx context.Context, realm, name string) error
- func (s *Service) DeleteTrigger(ctx context.Context, realm, name string) error
- func (s *Service) GetAuthKey(ctx context.Context, realm string) (string, error)
- func (s *Service) GetDatastreamMaximumStorageRetention(ctx context.Context, realm string) (int64, error)
- func (s *Service) GetDeviceRegistrationLimit(ctx context.Context, realm string) (*int32, error)
- func (s *Service) GetInterface(ctx context.Context, realm, name string, major int) (json.RawMessage, error)
- func (s *Service) GetPolicy(ctx context.Context, realm, name string) (json.RawMessage, error)
- func (s *Service) GetTrigger(ctx context.Context, realm, name string) (json.RawMessage, error)
- func (s *Service) InstallInterface(ctx context.Context, realm string, def []byte) (*store.StoredInterface, error)
- func (s *Service) ListInterfaceMajors(ctx context.Context, realm, name string) ([]int, error)
- func (s *Service) ListInterfaces(ctx context.Context, realm string) ([]string, error)
- func (s *Service) ListInterfacesDetailed(ctx context.Context, realm string) ([]json.RawMessage, error)
- func (s *Service) ListPolicies(ctx context.Context, realm string) ([]string, error)
- func (s *Service) ListTriggers(ctx context.Context, realm string) ([]string, error)
- func (s *Service) SetAuthKey(ctx context.Context, realm, keyPEM string) error
- func (s *Service) UpdateInterface(ctx context.Context, realm, urlName string, urlMajor int, def []byte) (*store.StoredInterface, error)
- func (s *Service) WithDisconnecter(d Disconnecter) *Service
Constants ¶
const APICompatVersion = "1.2.2"
APICompatVersion is the upstream Realm Management API level Astrate emulates, reported by GET /v1/{realm}/version. The Astarte Dashboard feature-gates UI sections on it (the Trigger Delivery Policies page requires >= 1.1.1), so this is a compatibility declaration, not Astrate's own release version (docs/COMPATIBILITY.md). Bump rule: only in the same change that completes the full surface of the new level, after reconciling every row in docs/UPSTREAM-EXPERIMENTAL.md tagged with it — never via configuration, never speculatively.
Variables ¶
var ( // ErrNameMismatch is a PUT whose body interface_name disagrees with the // URL (upstream name_not_matching, #62). ErrNameMismatch = errors.New("realm: interface name does not match") // ErrMajorMismatch is a PUT whose body version_major disagrees with the // URL (upstream major_version_not_matching, #62). ErrMajorMismatch = errors.New("realm: interface major does not match") // ErrNameCollision rejects an install whose name equals an installed one // modulo case and hyphens (upstream interface_name_collision, #62). ErrNameCollision = errors.New("realm: interface name collision") )
var ErrMaximumDatabaseRetentionExceeded = errors.New("realm: maximum_database_retention_exceeded")
ErrMaximumDatabaseRetentionExceeded rejects an interface install/update whose mapping TTL exceeds the realm's datastream_maximum_storage_retention ceiling (upstream error_name maximum_database_retention_exceeded, #72).
var ErrValidation = errors.New("realm: validation failed")
ErrValidation wraps a request that is well-formed JSON but violates an interface/trigger schema rule (maps to a 422). Use errors.Is against it and fmt.Errorf("%w: ...", ErrValidation, ...) to attach the detail.
Functions ¶
This section is empty.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API is the /realmmanagement/v1 HTTP surface (docs/ROADMAP.md §8.1 file 7.2). Every route is guarded by a realm JWT carrying a_rma.
type Disconnecter ¶ added in v0.2.0
Disconnecter force-closes a device's live MQTT session (*broker.Broker satisfies it). Device deletion kicks the session before wiping the rows, mirroring upstream's disconnect-first deletion order. A nil Disconnecter skips the kick; the deleted device is then refused at its next reconnect or credential request instead.
type Invalidator ¶
type Invalidator interface {
RefreshInterfaces(ctx context.Context, realmID int16) error
RefreshTriggers(ctx context.Context, realmID int16) error
}
Invalidator is the in-process cache-invalidation callback the engine satisfies (*engine.Engine's RefreshInterfaces / RefreshTriggers). After a realm mutation the service refreshes the engine's compiled snapshot so the change takes effect without waiting for the LISTEN/NOTIFY round-trip. A nil Invalidator disables the in-process path; the store NOTIFY still fires.
type OnDeletionFunc ¶ added in v0.2.0
OnDeletionFunc is called around a synchronous device delete so the engine can emit device_deletion_started / device_deletion_finished (issue #21). The callback receives the realm name, encoded device ID, and the instant.
type Service ¶
type Service struct {
// OnDeletionStart / OnDeletionFinish bookend DeleteDevice (nil-safe).
OnDeletionStart OnDeletionFunc
OnDeletionFinish OnDeletionFunc
// contains filtered or unexported fields
}
Service implements the Realm Management business logic over the store.
func NewService ¶
NewService builds the service. inv may be nil (e.g. management-only deployments without a local engine); log defaults to slog.Default().
func (*Service) CreatePolicy ¶ added in v0.2.0
func (s *Service) CreatePolicy(ctx context.Context, realm string, def []byte) (*store.TriggerPolicy, error)
CreatePolicy validates and stores a delivery policy (upstream POST /policies). Duplicates yield store.ErrAlreadyExists.
func (*Service) CreateTrigger ¶
func (s *Service) CreateTrigger(ctx context.Context, realm string, def []byte) (*store.Trigger, error)
CreateTrigger validates a trigger definition (name + action + simple triggers, via triggers.Compile — the same validation the engine applies) and installs it. A duplicate name yields store.ErrAlreadyExists. If the trigger references a policy, that policy must already exist in the realm; otherwise the request is rejected as a validation error.
func (*Service) DeleteDevice ¶ added in v0.2.0
DeleteDevice synchronously removes a device and all its data (upstream starts an async deletion with a transient deletion_in_progress state; Astrate is single-process and deletes in one transaction — docs/COMPATIBILITY.md). Emits device_deletion_started immediately before the store delete and device_deletion_finished immediately after (issue #21: back-to-back around the sync path so imported trigger configs still fire). finished is emitted even when the store delete fails, so a started lifecycle always closes.
func (*Service) DeleteInterface ¶
DeleteInterface removes an interface major. The store enforces the upstream draining rules (store.ErrInterfaceMajorNotZero, store.ErrInterfaceInUse); a lookup miss is marked errMajorNotFound for the HTTP layer (#62).
func (*Service) DeletePolicy ¶ added in v0.2.0
DeletePolicy removes a policy. The request is rejected if any trigger in the realm still references this policy.
func (*Service) DeleteTrigger ¶
DeleteTrigger removes one trigger by name.
func (*Service) GetAuthKey ¶
GetAuthKey returns the realm's JWT public key PEM (upstream GET /config/auth → {"jwt_public_key_pem": "..."}). Astrate stores a list for rotation; the wire field carries them concatenated, which the verifier already splits into individual keys.
func (*Service) GetDatastreamMaximumStorageRetention ¶ added in v0.2.0
func (s *Service) GetDatastreamMaximumStorageRetention(ctx context.Context, realm string) (int64, error)
GetDatastreamMaximumStorageRetention returns the realm's datastream maximum storage retention in seconds, upstream GET /config/datastream_maximum_storage_retention (served since 1.2.0). An unset ceiling renders as 0 — the #60 wire contract (upstream answers null here, a recorded deviation), pinned by tests.
func (*Service) GetDeviceRegistrationLimit ¶ added in v0.2.0
GetDeviceRegistrationLimit returns the realm's device registration limit (nil = unlimited), upstream GET /config/device_registration_limit.
func (*Service) GetInterface ¶
func (s *Service) GetInterface(ctx context.Context, realm, name string, major int) (json.RawMessage, error)
GetInterface returns the stored definition JSON of one interface major (upstream GET /interfaces/{name}/{major}).
func (*Service) GetTrigger ¶
GetTrigger returns one trigger's definition JSON.
func (*Service) InstallInterface ¶
func (s *Service) InstallInterface(ctx context.Context, realm string, def []byte) (*store.StoredInterface, error)
InstallInterface validates and installs a new interface major (docs/ROADMAP.md §8.1). A duplicate (name, major) yields store.ErrAlreadyExists; a schema violation yields ErrValidation — carrying a *interfaceschema.ViolationsError when the rejection has a probe-verified upstream wire shape (#61). Documents posted with legacy alias fields (quality/aggregate/path) are stored canonically so GET renders them the way upstream does.
func (*Service) ListInterfaceMajors ¶
ListInterfaceMajors returns the installed major versions of one interface name (upstream GET /interfaces/{name}), ascending. An unknown name yields store.ErrNotFound.
func (*Service) ListInterfaces ¶
ListInterfaces returns the distinct interface names installed in the realm (upstream GET /interfaces), sorted for stable output.
func (*Service) ListInterfacesDetailed ¶ added in v0.2.0
func (s *Service) ListInterfacesDetailed(ctx context.Context, realm string) ([]json.RawMessage, error)
ListInterfacesDetailed renders the additive 1.4-style detailed listing (issue #66): one fully materialised document per installed interface major, sorted by (name, major). The names-only listing upstream 1.2 serves stays on ListInterfaces.
func (*Service) ListPolicies ¶ added in v0.2.0
ListPolicies returns the realm's policy names.
func (*Service) ListTriggers ¶
ListTriggers returns the realm's trigger names, sorted.
func (*Service) SetAuthKey ¶
SetAuthKey rotates the realm's JWT public key (upstream PUT /config/auth). The supplied PEM may concatenate multiple keys for a rotation window.
func (*Service) UpdateInterface ¶
func (s *Service) UpdateInterface(ctx context.Context, realm, urlName string, urlMajor int, def []byte) (*store.StoredInterface, error)
UpdateInterface applies a minor upgrade, enforcing the additive-only upstream parity rules via interfaceschema.CheckMinorUpgrade (no mutated mapping attributes, same type/ownership/aggregation, strictly higher minor). urlName/urlMajor are the interface identity from the URL path: the parsed body must agree with both (upstream 409s the mismatches, #62), and a lookup miss on that identity yields the "major not found" marker.
func (*Service) WithDisconnecter ¶ added in v0.2.0
func (s *Service) WithDisconnecter(d Disconnecter) *Service
WithDisconnecter attaches the broker seam used to kick a live session at device deletion (nil-safe, mirrors housekeeping's Reloader wiring).