Documentation
¶
Overview ¶
Package ddm implements declarations, membership, snapshots, synchronization tokens and status handling for declarative device management.
Design ¶
The engine serves Apple's four endpoint operations over a transactional storage contract. Canonical content determines tokens, per-enrollment snapshots preserve advertised versions, and full status reports replace stored state atomically. Device and user channels have independent membership. Resolver and Expander hooks support dynamic assignments and per-enrollment content.
Persistence implementations live in storage/ddm and server/ddmstore. Transport adapters live in server/ddmadapter. Transactional change rows are drained by server/ddmsync, which also supplies lifecycle cleanup hooks. The engine does not dispatch commands or pushes directly.
References ¶
- Decision record 0019: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0019-canonical-json-and-ddm-tokens.md
- Decision record 0020: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0020-ddm-engine-membership-and-storage.md
- Decision record 0021: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0021-status-reports-and-subscriptions.md
- Decision record 0022: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0022-change-notifier.md
- Threat model: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/security/threat-model.md
- Apple: https://developer.apple.com/documentation/devicemanagement/integrating-declarative-management
- Apple: https://developer.apple.com/documentation/devicemanagement/declarativemanagementrequest
- Apple: https://developer.apple.com/documentation/devicemanagement/devicemanagement-declarations
- Apple: https://developer.apple.com/documentation/devicemanagement/status-items
- Schema: third_party/device-management/declarative/protocol/*.yaml
- Schema: third_party/device-management/declarative/declarations/**, declarative/status/**
- Schema: third_party/device-management/mdm/checkin/declarativemanagement.yaml
- RFC 8785 (JSON Canonicalization Scheme): https://www.rfc-editor.org/rfc/rfc8785
Index ¶
- Constants
- Variables
- func DeclarationsToken(refs []DeclarationRef) string
- func ParseKind(s string) (schemaddm.Kind, error)
- func RenderDeclaration(canonical []byte, serverToken string) ([]byte, error)
- func RenderDeclarationItems(snap *Snapshot) ([]byte, error)
- func RenderTokens(token string, at time.Time) ([]byte, error)
- func TokenFor(canonical []byte) string
- type AssignmentStore
- type Change
- type ChangeStore
- type Config
- type Declaration
- type DeclarationQuery
- type DeclarationRef
- type DeclarationStatus
- type DeclarationStore
- type DeclarationVersion
- type Endpoint
- type Engine
- func (e *Engine) AddToSet(ctx context.Context, set, identifier string) (bool, error)
- func (e *Engine) AssignDeclaration(ctx context.Context, id mdm.EnrollmentID, identifier string) (bool, error)
- func (e *Engine) AssignSet(ctx context.Context, id mdm.EnrollmentID, set string) (bool, error)
- func (e *Engine) ClearEnrollment(ctx context.Context, id mdm.EnrollmentID) error
- func (e *Engine) ClientCapabilities(ctx context.Context, id mdm.EnrollmentID) (*status.ManagementClientCapabilitiesCapabilities, error)
- func (e *Engine) Declaration(ctx context.Context, id mdm.EnrollmentID, kind schemaddm.Kind, ...) ([]byte, error)
- func (e *Engine) DeclarationItems(ctx context.Context, id mdm.EnrollmentID) ([]byte, error)
- func (e *Engine) DeclarationSets(ctx context.Context, identifier string) ([]string, error)
- func (e *Engine) DeclarationStatus(ctx context.Context, id mdm.EnrollmentID) ([]DeclarationStatus, error)
- func (e *Engine) DeclarationStatusByIdentifier(ctx context.Context, identifier string, p paging.Page) (paging.Result[EnrollmentDeclarationStatus], error)
- func (e *Engine) DeleteDeclaration(ctx context.Context, identifier string) error
- func (e *Engine) DeleteSet(ctx context.Context, name string) error
- func (e *Engine) EnrollmentDeclarations(ctx context.Context, id mdm.EnrollmentID) ([]string, error)
- func (e *Engine) EnrollmentIdentity(ctx context.Context, rawID string) (mdm.EnrollmentID, error)
- func (e *Engine) EnrollmentSets(ctx context.Context, id mdm.EnrollmentID) ([]string, error)
- func (e *Engine) GetDeclaration(ctx context.Context, identifier string) (*Declaration, error)
- func (e *Engine) GetSet(ctx context.Context, name string) (*Set, error)
- func (e *Engine) Handle(ctx context.Context, id mdm.EnrollmentID, endpoint string, data []byte) (Response, error)
- func (e *Engine) ListDeclarations(ctx context.Context, q DeclarationQuery, p paging.Page) (paging.Result[Declaration], error)
- func (e *Engine) ListSets(ctx context.Context, p paging.Page) (paging.Result[Set], error)
- func (e *Engine) Logger() *slog.Logger
- func (e *Engine) Manifest(ctx context.Context, id mdm.EnrollmentID) (*Snapshot, error)
- func (e *Engine) PruneVersions(ctx context.Context) (int64, error)
- func (e *Engine) PutDeclaration(ctx context.Context, raw []byte) (*Declaration, bool, error)
- func (e *Engine) PutSet(ctx context.Context, name string) (bool, error)
- func (e *Engine) RemoveFromSet(ctx context.Context, set, identifier string) (bool, error)
- func (e *Engine) SetDeclarations(ctx context.Context, set string) ([]string, error)
- func (e *Engine) SetEnrollments(ctx context.Context, set string, p paging.Page) (paging.Result[mdm.EnrollmentID], error)
- func (e *Engine) Status(ctx context.Context, id mdm.EnrollmentID, body []byte) (*StatusOutcome, error)
- func (e *Engine) StatusErrors(ctx context.Context, id mdm.EnrollmentID, p paging.Page) (paging.Result[StatusError], error)
- func (e *Engine) StatusReports(ctx context.Context, id mdm.EnrollmentID, p paging.Page) (paging.Result[StatusReportRecord], error)
- func (e *Engine) StatusValues(ctx context.Context, id mdm.EnrollmentID, q StatusValueQuery, p paging.Page) (paging.Result[StatusValue], error)
- func (e *Engine) Store() Store
- func (e *Engine) Tokens(ctx context.Context, id mdm.EnrollmentID) ([]byte, error)
- func (e *Engine) Touch(ctx context.Context, ids []mdm.EnrollmentID, reason string) error
- func (e *Engine) UnassignDeclaration(ctx context.Context, id mdm.EnrollmentID, identifier string) (bool, error)
- func (e *Engine) UnassignSet(ctx context.Context, id mdm.EnrollmentID, set string) (bool, error)
- type EnrollmentDeclarationStatus
- type Expander
- type Op
- type Resolver
- type Response
- type Set
- type SetStore
- type Snapshot
- type SnapshotItem
- type SnapshotStore
- type StatusError
- type StatusOutcome
- type StatusReportRecord
- type StatusStore
- type StatusUpdate
- type StatusValue
- type StatusValueQuery
- type Store
- type Subscriptions
- type Tx
Constants ¶
const ( ReasonDeclaration = "declaration" ReasonSet = "set" ReasonAssignment = "assignment" ReasonTouch = "touch" )
Change reasons recorded on ddm_changes rows.
const ( DefaultMaxStatusBytes = 1 << 20 DefaultKeepReports = 10 )
Defaults.
const MaxIdentifierBytes = 64
MaxIdentifierBytes is Apple's guidance for Identifier and ServerToken values ("should not exceed 64 octets").
const StatusItemClientCapabilities = status.StatusItemTypeManagementClientCapabilities
StatusItemClientCapabilities is the status item devices always report.
const StatusItemDeclarations = status.StatusItemTypeManagementDeclarations
StatusItemDeclarations is the status item carrying per-declaration state.
const SubscriptionIdentifier = "com.deploymenttheory.mdm.status-subscriptions"
SubscriptionIdentifier names the synthesised status-subscriptions declaration. An admin-supplied declaration with this identifier replaces the synthesised one.
const TimestampLayout = "2006-01-02T15:04:05Z"
TimestampLayout is the SyncTokens Timestamp format: whole seconds, UTC.
Variables ¶
var ( ErrNotFound = errors.New("ddm: not found") ErrConflict = errors.New("ddm: conflict") ErrInvalid = errors.New("ddm: invalid argument") ErrUnknownType = errors.New("ddm: unknown declaration type") ErrInvalidDeclaration = errors.New("ddm: declaration failed validation") ErrBadEndpoint = errors.New("ddm: malformed endpoint") ErrStatusTooLarge = errors.New("ddm: status report exceeds limit") ErrStatusMalformed = errors.New("ddm: malformed status report") ErrResolver = errors.New("ddm: membership resolver failed") ErrExpander = errors.New("ddm: expander failed") ErrNotifier = errors.New("ddm: notifier") )
Errors shared by the engine and every store backend.
var DefaultSubscriptionBaseline = []string{
"device.identifier.serial-number", "device.identifier.udid",
"device.model.family", "device.model.identifier", "device.model.marketing-name",
"device.operating-system.build-version", "device.operating-system.family",
"device.operating-system.marketing-name", "device.operating-system.version",
"management.client-capabilities", "management.declarations",
}
DefaultSubscriptionBaseline is used until a device reports which status items it supports.
var DefaultSubscriptionExclude = []string{"test."}
DefaultSubscriptionExclude drops Apple's test items from subscriptions.
var ErrNoStore = errors.New("ddm: store is required")
ErrNoStore is returned by New when Config.Store is nil.
var StandaloneKinds = []schemaddm.Kind{schemaddm.KindActivation, schemaddm.KindAsset, schemaddm.KindConfiguration, schemaddm.KindManagement}
StandaloneKinds are the declaration families a device fetches by name.
Functions ¶
func DeclarationsToken ¶
func DeclarationsToken(refs []DeclarationRef) string
DeclarationsToken derives the manifest token from the sorted refs: sha256 over each kind, identifier, and server token written with a 4-byte length prefix. It is independent of input order and of the wall clock, distinguishes ("ab","c") from ("a","bc"), and is 64 hex characters, within Apple's 64-octet guidance (decision record 0019).
func RenderDeclaration ¶
RenderDeclaration returns the wire form of a declaration: its canonical members plus the ServerToken the device must echo back.
func RenderDeclarationItems ¶
RenderDeclarationItems renders a snapshot as a DeclarationItemsResponse.
func RenderTokens ¶
RenderTokens renders {"SyncTokens":{"DeclarationsToken":..,"Timestamp":..}}.
Types ¶
type AssignmentStore ¶
type AssignmentStore interface {
// EnrollmentIdentity resolves a previously stored raw ID to its immutable identity.
EnrollmentIdentity(ctx context.Context, rawID string) (mdm.EnrollmentID, error)
AssignSet(ctx context.Context, id mdm.EnrollmentID, set string, at time.Time) (changed bool, err error)
UnassignSet(ctx context.Context, id mdm.EnrollmentID, set string) (changed bool, err error)
EnrollmentSets(ctx context.Context, id mdm.EnrollmentID) ([]string, error)
SetEnrollments(ctx context.Context, set string, p paging.Page) (paging.Result[mdm.EnrollmentID], error)
AssignDeclaration(ctx context.Context, id mdm.EnrollmentID, identifier string, at time.Time) (changed bool, err error)
UnassignDeclaration(ctx context.Context, id mdm.EnrollmentID, identifier string) (changed bool, err error)
// EnrollmentDeclarations lists direct assignments only, sorted.
EnrollmentDeclarations(ctx context.Context, id mdm.EnrollmentID) ([]string, error)
// StaticDeclarations is the union of direct assignments and set members,
// deduplicated and sorted by identifier. Empty for an unknown id.
StaticDeclarations(ctx context.Context, id mdm.EnrollmentID) ([]Declaration, error)
// AffectedEnrollments lists every enrollment whose static membership
// includes any of the identifiers or sets, deduplicated and sorted.
AffectedEnrollments(ctx context.Context, identifiers, sets []string) ([]mdm.EnrollmentID, error)
}
AssignmentStore binds enrollments to sets and to single declarations.
type Change ¶
type Change struct {
Seq int64
ID mdm.EnrollmentID
Reason string
CreatedAt time.Time
Attempts int
LastError string
NextAttemptAt time.Time
}
Change is a pending notification for one enrollment.
type ChangeStore ¶
type ChangeStore interface {
// RecordChanges appends one row per id.
RecordChanges(ctx context.Context, ids []mdm.EnrollmentID, reason string, at time.Time) error
// PendingChanges returns rows due at or before now, oldest first.
PendingChanges(ctx context.Context, now time.Time, limit int) ([]Change, error)
CompleteChanges(ctx context.Context, seqs []int64) error
// FailChanges records the error and the next attempt time; rows are
// never deleted by a failure.
FailChanges(ctx context.Context, seqs []int64, msg string, nextAttempt time.Time) error
// ChangeStats counts rows due now and rows that have failed at least
// once.
ChangeStats(ctx context.Context, now time.Time) (pending, failed int64, err error)
}
ChangeStore queues notifications.
type Config ¶
type Config struct {
Store Store
Resolvers []Resolver
Expander Expander
Bus *event.Bus
Clock clock.Clock
Logger *slog.Logger
// Target supplies the validation target for uploads; nil validates for
// any OS.
Target func(ctx context.Context) support.Target
// MaxStatusBytes bounds a status report; default 1 MiB.
MaxStatusBytes int
// Structural limits apply before decoding or storing a status report.
MaxStatusDepth int
MaxStatusPathBytes int
MaxStatusItems int
// KeepReports bounds raw status reports kept per enrollment; default 10.
KeepReports int
Subscriptions Subscriptions
}
Config builds an Engine.
type Declaration ¶
type Declaration struct {
Identifier string
Type string
Kind schemaddm.Kind
ServerToken string
Canonical []byte
CreatedAt time.Time
// UpdatedAt is the last time ServerToken changed.
UpdatedAt time.Time
}
Declaration is a stored declaration: the canonical JSON of {Identifier, Payload, Type} and the token derived from it.
func ParseDeclaration ¶
func ParseDeclaration(raw []byte, target support.Target) (*Declaration, error)
ParseDeclaration validates an uploaded declaration and derives its canonical bytes and ServerToken (decision record 0019). The upload's own ServerToken is ignored: tokens are derived, never authored. Type must be one of the standalone families in schema/ddm and the generated Validate must pass for target.
type DeclarationQuery ¶
DeclarationQuery filters ListDeclarations. Zero values mean "any".
type DeclarationRef ¶
DeclarationRef names one declaration in a manifest.
func SortRefs ¶
func SortRefs(refs []DeclarationRef) []DeclarationRef
SortRefs orders refs by (kind, identifier, token), the order every manifest and token computation uses.
type DeclarationStatus ¶
type DeclarationStatus struct {
Kind schemaddm.Kind
Identifier string
ServerToken string
Active bool
// Valid is unknown, invalid, or valid as the device reported it.
Valid string
// Reasons is the raw JSON array of reasons, nil when none.
Reasons []byte
FirstSeen time.Time
LastSeen time.Time
}
DeclarationStatus is what a device last reported about one declaration.
type DeclarationStore ¶
type DeclarationStore interface {
// PutDeclaration upserts by Identifier. changed is false when the stored
// ServerToken already equals d.ServerToken; nothing is written then.
// ErrConflict when the identifier exists with a different Kind. Every
// accepted change also records a DeclarationVersion.
PutDeclaration(ctx context.Context, d *Declaration) (changed bool, err error)
// GetDeclaration returns the current revision or ErrNotFound.
GetDeclaration(ctx context.Context, identifier string) (*Declaration, error)
// GetDeclarationVersion returns one revision or ErrNotFound.
GetDeclarationVersion(ctx context.Context, identifier, serverToken string) (*DeclarationVersion, error)
// DeleteDeclaration removes the declaration, its versions, set
// memberships, and direct assignments. ErrNotFound when absent.
DeleteDeclaration(ctx context.Context, identifier string) error
// ListDeclarations pages by identifier.
ListDeclarations(ctx context.Context, q DeclarationQuery, p paging.Page) (paging.Result[Declaration], error)
// PruneVersions deletes revisions that are neither current nor named by
// a snapshot item and returns how many.
PruneVersions(ctx context.Context) (int64, error)
}
DeclarationStore persists declarations and their revisions.
type DeclarationVersion ¶
type DeclarationVersion struct {
Identifier string
Type string
ServerToken string
Canonical []byte
CreatedAt time.Time
}
DeclarationVersion is one revision of a declaration, kept so a fetch can serve the exact bytes a manifest advertised.
type Endpoint ¶
type Endpoint struct {
Op Op
// Kind and Identifier are set for OpDeclaration only.
Kind schemaddm.Kind
Identifier string
}
Endpoint is a parsed DeclarativeManagement Endpoint value.
func ParseEndpoint ¶
ParseEndpoint parses "tokens", "declaration-items", "status", or "declaration/<kind>/<identifier>" where kind is activation, asset, configuration, or management. Anything else is ErrBadEndpoint.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine serves declarative management for enrollments.
func (*Engine) AssignDeclaration ¶
func (e *Engine) AssignDeclaration(ctx context.Context, id mdm.EnrollmentID, identifier string) (bool, error)
AssignDeclaration binds one declaration directly to an enrollment.
func (*Engine) ClearEnrollment ¶
ClearEnrollment forgets everything the engine holds for one enrollment: set and declaration assignments, the snapshot, status, and pending changes. Declarations and sets themselves are untouched.
func (*Engine) ClientCapabilities ¶
func (e *Engine) ClientCapabilities(ctx context.Context, id mdm.EnrollmentID) (*status.ManagementClientCapabilitiesCapabilities, error)
ClientCapabilities decodes the last reported management.client-capabilities item, or ErrNotFound when the device never reported it. The item is read defensively (decision record 0021, claim 7): a member that does not fit Apple's schema is logged and left empty rather than failing the caller, because devices have sent partial or oddly shaped capabilities and the check-in path must keep serving them.
func (*Engine) Declaration ¶
func (e *Engine) Declaration(ctx context.Context, id mdm.EnrollmentID, kind schemaddm.Kind, identifier string) ([]byte, error)
Declaration serves one declaration as the enrollment's manifest advertised it. ErrNotFound (404 on the wire) when the declaration is not in the manifest, has the wrong kind, or was deleted since.
func (*Engine) DeclarationItems ¶
DeclarationItems renders the DeclarationItemsResponse for an enrollment with all four arrays present, as Apple's schema requires.
func (*Engine) DeclarationSets ¶
DeclarationSets lists the sets containing a declaration.
func (*Engine) DeclarationStatus ¶
func (e *Engine) DeclarationStatus(ctx context.Context, id mdm.EnrollmentID) ([]DeclarationStatus, error)
DeclarationStatus lists what an enrollment last reported per declaration.
func (*Engine) DeclarationStatusByIdentifier ¶
func (e *Engine) DeclarationStatusByIdentifier(ctx context.Context, identifier string, p paging.Page) (paging.Result[EnrollmentDeclarationStatus], error)
DeclarationStatusByIdentifier pages through every enrollment's status for one declaration.
func (*Engine) DeleteDeclaration ¶
DeleteDeclaration removes a declaration and notifies every enrollment that had it, so devices receive 404 on their next fetch and drop it.
func (*Engine) EnrollmentDeclarations ¶
EnrollmentDeclarations lists an enrollment's direct assignments.
func (*Engine) EnrollmentIdentity ¶ added in v0.3.2
EnrollmentIdentity resolves the identity used by assignments and snapshots.
func (*Engine) EnrollmentSets ¶
EnrollmentSets lists an enrollment's sets.
func (*Engine) GetDeclaration ¶
GetDeclaration returns the current revision.
func (*Engine) Handle ¶
func (e *Engine) Handle(ctx context.Context, id mdm.EnrollmentID, endpoint string, data []byte) (Response, error)
Handle serves one DeclarativeManagement check-in for the adapters. Malformed endpoints are ErrBadEndpoint; a status endpoint needs data.
func (*Engine) ListDeclarations ¶
func (e *Engine) ListDeclarations(ctx context.Context, q DeclarationQuery, p paging.Page) (paging.Result[Declaration], error)
ListDeclarations pages through declarations.
func (*Engine) Logger ¶
Logger returns the engine's logger, never nil, so a component built around an engine can inherit its logging rather than invent one.
func (*Engine) PruneVersions ¶
PruneVersions deletes declaration revisions nothing references.
func (*Engine) PutDeclaration ¶
PutDeclaration validates and stores a declaration. changed is false when an equivalent declaration was already stored, in which case no enrollment is notified. Every affected enrollment is queued for notification inside the same transaction.
func (*Engine) RemoveFromSet ¶
RemoveFromSet removes a declaration from a set and notifies the set's enrollments.
func (*Engine) SetDeclarations ¶
SetDeclarations lists a set's members.
func (*Engine) SetEnrollments ¶
func (e *Engine) SetEnrollments(ctx context.Context, set string, p paging.Page) (paging.Result[mdm.EnrollmentID], error)
SetEnrollments pages through a set's enrollments.
func (*Engine) Status ¶
func (e *Engine) Status(ctx context.Context, id mdm.EnrollmentID, body []byte) (*StatusOutcome, error)
Status stores a device's status report (decision record 0021): the raw report, every status item as canonical JSON keyed by its nested path, the typed management.declarations rows, and the Errors array. A full report replaces the enrollment's status; declarations absent from it are removed.
func (*Engine) StatusErrors ¶
func (e *Engine) StatusErrors(ctx context.Context, id mdm.EnrollmentID, p paging.Page) (paging.Result[StatusError], error)
StatusErrors pages through an enrollment's reported errors, newest first.
func (*Engine) StatusReports ¶
func (e *Engine) StatusReports(ctx context.Context, id mdm.EnrollmentID, p paging.Page) (paging.Result[StatusReportRecord], error)
StatusReports pages through retained raw reports, newest first.
func (*Engine) StatusValues ¶
func (e *Engine) StatusValues(ctx context.Context, id mdm.EnrollmentID, q StatusValueQuery, p paging.Page) (paging.Result[StatusValue], error)
StatusValues pages through an enrollment's status item values.
func (*Engine) Touch ¶
Touch queues a notification for enrollments without changing their declarations: the first DeclarativeManagement command that enables the engine on a device, or a resolver-driven change.
func (*Engine) UnassignDeclaration ¶
func (e *Engine) UnassignDeclaration(ctx context.Context, id mdm.EnrollmentID, identifier string) (bool, error)
UnassignDeclaration removes a direct binding.
func (*Engine) UnassignSet ¶
UnassignSet removes a set binding and notifies the enrollment.
type EnrollmentDeclarationStatus ¶
type EnrollmentDeclarationStatus struct {
ID mdm.EnrollmentID
DeclarationStatus
}
EnrollmentDeclarationStatus is DeclarationStatus for one enrollment, returned by identifier-centred queries.
type Expander ¶
type Expander interface {
Expand(ctx context.Context, id mdm.EnrollmentID, d *Declaration) ([]byte, error)
}
Expander may rewrite a declaration's canonical bytes for one enrollment (variable substitution). Returning nil, or bytes equal to d.Canonical, means unchanged. The bytes returned must be a JSON object; they are canonicalised and the served token is derived from them.
type Op ¶
type Op int
Op is the operation a DeclarativeManagement check-in requests.
Operations, in the order Apple lists the Endpoint values.
type Resolver ¶
Resolver adds declarations to an enrollment's manifest dynamically, for example by device attribute or by an external group. Errors fail closed: serving that enrollment returns ErrResolver rather than a partial manifest.
type Response ¶
type Response struct {
Body []byte
// Status is 200, or 404 when a declaration is not part of the
// enrollment's manifest (Apple: the device then removes it).
Status int
}
Response is what a device-facing adapter writes back.
type SetStore ¶
type SetStore interface {
// PutSet creates the set; created is false when it already existed.
PutSet(ctx context.Context, name string, at time.Time) (created bool, err error)
// DeleteSet removes the set, its memberships, and its assignments.
DeleteSet(ctx context.Context, name string) error
GetSet(ctx context.Context, name string) (*Set, error)
ListSets(ctx context.Context, p paging.Page) (paging.Result[Set], error)
// AddSetDeclaration returns ErrNotFound when either side is unknown.
AddSetDeclaration(ctx context.Context, set, identifier string, at time.Time) (changed bool, err error)
RemoveSetDeclaration(ctx context.Context, set, identifier string) (changed bool, err error)
// SetDeclarations lists member identifiers, sorted; ErrNotFound for an
// unknown set.
SetDeclarations(ctx context.Context, set string) ([]string, error)
// DeclarationSets lists the sets containing identifier, sorted.
DeclarationSets(ctx context.Context, identifier string) ([]string, error)
}
SetStore persists sets and their membership.
type Snapshot ¶
type Snapshot struct {
ID mdm.EnrollmentID
DeclarationsToken string
Items []SnapshotItem
TokenChangedAt time.Time
RefreshedAt time.Time
}
Snapshot is the manifest an enrollment was last served, with the token it was told. TokenChangedAt is the Timestamp in the tokens response.
type SnapshotItem ¶
type SnapshotItem struct {
DeclarationRef
// BaseToken is the stored declaration's token; ServerToken differs only
// when an Expander rewrote the bytes for this enrollment.
BaseToken string
// Expanded holds the per-enrollment canonical bytes when they differ
// from the stored declaration; nil otherwise.
Expanded []byte
}
SnapshotItem is one manifest entry as advertised to an enrollment.
func SortRefsItems ¶
func SortRefsItems(items []SnapshotItem) []SnapshotItem
SortRefsItems orders snapshot items the way manifests are rendered.
type SnapshotStore ¶
type SnapshotStore interface {
// PutSnapshot replaces the snapshot and its items atomically.
PutSnapshot(ctx context.Context, s *Snapshot) error
Snapshot(ctx context.Context, id mdm.EnrollmentID) (*Snapshot, error)
}
SnapshotStore keeps the manifest last served per enrollment.
type StatusError ¶
StatusError is one entry of a report's Errors array.
type StatusOutcome ¶
type StatusOutcome struct {
Seq int64
Removed []DeclarationRef
RemovedValues []string
PrunedReports int64
}
StatusOutcome reports what PutStatus changed.
type StatusReportRecord ¶
StatusReportRecord is one raw report as received.
type StatusStore ¶
type StatusStore interface {
// PutStatus applies one report atomically: appends the raw report,
// upserts declaration rows and values (LastSeen bumped, FirstSeen kept),
// appends errors, and for a full report deletes declaration rows and
// values absent from the update. It prunes raw reports beyond
// KeepReports, oldest first.
PutStatus(ctx context.Context, id mdm.EnrollmentID, u StatusUpdate) (StatusOutcome, error)
// DeclarationStatus lists rows sorted by (kind, identifier).
DeclarationStatus(ctx context.Context, id mdm.EnrollmentID) ([]DeclarationStatus, error)
DeclarationStatusByIdentifier(ctx context.Context, identifier string, p paging.Page) (paging.Result[EnrollmentDeclarationStatus], error)
// StatusValues pages by path.
StatusValues(ctx context.Context, id mdm.EnrollmentID, q StatusValueQuery, p paging.Page) (paging.Result[StatusValue], error)
// StatusErrors pages newest first.
StatusErrors(ctx context.Context, id mdm.EnrollmentID, p paging.Page) (paging.Result[StatusError], error)
// StatusReports pages newest first.
StatusReports(ctx context.Context, id mdm.EnrollmentID, p paging.Page) (paging.Result[StatusReportRecord], error)
}
StatusStore persists what devices report.
type StatusUpdate ¶
type StatusUpdate struct {
Raw []byte
ReceivedAt time.Time
FullReport bool
// HasDeclarations is false when the report carried no
// management.declarations item, in which case declaration rows are
// left untouched even for a full report.
HasDeclarations bool
Declarations []DeclarationStatus
Values []StatusValue
Errors []StatusError
// KeepReports bounds the raw reports retained per enrollment.
KeepReports int
}
StatusUpdate is a parsed report ready for PutStatus.
type StatusValue ¶
StatusValue is one status item value as canonical JSON, keyed by its dotted path (array elements keep their index as a path segment).
type StatusValueQuery ¶
type StatusValueQuery struct {
PathPrefix string
}
StatusValueQuery filters StatusValues by path prefix.
type Store ¶
type Store interface {
Tx
// Update runs fn in one transaction; an error rolls everything back.
Update(ctx context.Context, fn func(tx Tx) error) error
}
Store is one backend. Methods called outside Update commit on their own.
type Subscriptions ¶
type Subscriptions struct {
Enabled bool
// Baseline is used until a device reports its capabilities; nil means
// DefaultSubscriptionBaseline.
Baseline []string
// Exclude drops reported status items with these prefixes; nil means
// DefaultSubscriptionExclude.
Exclude []string
}
Subscriptions configures the synthesised status-subscriptions declaration (decision record 0021).
type Tx ¶
type Tx interface {
DeclarationStore
SetStore
AssignmentStore
SnapshotStore
StatusStore
ChangeStore
// ClearEnrollment deletes the enrollment's sets, assignments, snapshot,
// status, and pending changes. Absent state is not an error.
ClearEnrollment(ctx context.Context, id mdm.EnrollmentID) error
}
Tx is the view every store exposes inside Update.