kylokGo + Android SDK

Go API reference

Generated from Go declarations and purpose/usage comments. Development contracts may change before v1.

Store

go/adapters/filesystem/store.go:21

type Store struct {
    // contains filtered or unexported fields
}

Open

go/adapters/filesystem/store.go:25

// Open prepares a durable content-addressed directory; it never creates a temporary fallback.
// Usage: store, err := filesystem.Open("/var/lib/kylok/artifacts").
func Open(dir string) (*Store, error)

Open prepares a durable content-addressed directory; it never creates a temporary fallback. Usage: store, err := filesystem.Open("/var/lib/kylok/artifacts").

*Store.Put

go/adapters/filesystem/store.go:37

// Put verifies the digest and atomically publishes immutable bytes without replacing concurrent content.
// Usage: err := store.Put(ctx, digest, verifiedBytes).
func (s *Store) Put(ctx context.Context, digest string, data []byte) error

Put verifies the digest and atomically publishes immutable bytes without replacing concurrent content. Usage: err := store.Put(ctx, digest, verifiedBytes).

*Store.Open

go/adapters/filesystem/store.go:98

// Open verifies stored bytes and returns a seekable immutable snapshot, detecting on-disk corruption.
// Usage: reader, err := store.Open(ctx, digest); close reader after use.
func (s *Store) Open(ctx context.Context, digest string) (ports.ReadSeekCloser, error)

Open verifies stored bytes and returns a seekable immutable snapshot, detecting on-disk corruption. Usage: reader, err := store.Open(ctx, digest); close reader after use.

Options

go/adapters/postgres/store.go:16

type Options struct {
    Schema  string
    // Initialize requires CREATE on the database/schema and creates only Kylok-owned objects.
    // Leave false at runtime after initialization; missing/incomplete/wrong-version schemas fail closed.
    Initialize  bool
}

Options selects a dedicated existing schema or explicitly opts in to initializing it. Schema must be a lowercase SQL identifier, at most 63 characters; no search_path changes are made.

Store

go/adapters/postgres/store.go:26

type Store struct{ ports.StateStore }

Store implements the concurrent transactional state contract. PostgreSQL effects serialize per schema across processes using a transaction-level advisory lock. The host owns the pool, driver, TLS, credentials, limits and shutdown. No Close method owns that pool.

Open

go/adapters/postgres/store.go:31

// Open verifies a dedicated schema on a supplied pool, optionally initializing it atomically.
// It never closes or reconfigures the pool, including on failure. It does not join host transactions.
// Usage: store, err := postgres.Open(ctx, db, postgres.Options{Schema: "kylok", Initialize: true}).
func Open(ctx context.Context, db *sql.DB, options Options) (*Store, error)

Open verifies a dedicated schema on a supplied pool, optionally initializing it atomically. It never closes or reconfigures the pool, including on failure. It does not join host transactions. Usage: store, err := postgres.Open(ctx, db, postgres.Options{Schema: "kylok", Initialize: true}).

Store

go/adapters/sqlite/store.go:19

type Store struct {
    ports.StateStore
    // contains filtered or unexported fields
}

Store owns the SQLite pool and promotes the shared transactional state contract.

Open

go/adapters/sqlite/store.go:26

// Open requires a durable path. It never substitutes a temporary or memory DB.
// Usage: store, err := sqlite.Open(ctx, "/var/lib/kylok/state.sqlite").
func Open(ctx context.Context, path string) (*Store, error)

Open requires a durable path. It never substitutes a temporary or memory DB. Usage: store, err := sqlite.Open(ctx, "/var/lib/kylok/state.sqlite").

*Store.Close

go/adapters/sqlite/store.go:61

// Close releases the SQLite-owned pool after the host drains SDK users.
// Usage: defer store.Close().
func (s *Store) Close() error

Close releases the SQLite-owned pool after the host drains SDK users. Usage: defer store.Close().

*SDK.ListApplications

go/applications.go:15

// ListApplications lists verified managed APKs in one authorized scope.
// Usage: page, err := sdk.ListApplications(ctx, scope, "", 100); use the final SHA256 as the next cursor.
func (s *SDK) ListApplications(ctx context.Context, scope, after string, limit int) ([]Artifact, error)

ListApplications lists verified managed APKs in one authorized scope. Usage: page, err := sdk.ListApplications(ctx, scope, "", 100); use the final SHA256 as the next cursor.

*SDK.RegisterApplication

go/applications.go:38

// RegisterApplication publishes verified immutable metadata in one authorized scope.
// Usage: artifact, err := sdk.RegisterApplication(ctx, scope, verifiedAPK).
func (s *SDK) RegisterApplication(ctx context.Context, scope string, apk *provisioning.APK) (Artifact, error)

RegisterApplication publishes verified immutable metadata in one authorized scope. Usage: artifact, err := sdk.RegisterApplication(ctx, scope, verifiedAPK).

*SDK.AssignApplication

go/applications.go:64

// AssignApplication creates a desired revision and one durable install operation.
// Reusing a key with the same device/artifact returns the original operation.
// Usage: operation, err := sdk.AssignApplication(ctx, scope, deviceID, digest, requestKey, 24*time.Hour).
func (s *SDK) AssignApplication(ctx context.Context, scope, device, digest, key string, timeout time.Duration) (Operation, error)

AssignApplication creates a desired revision and one durable install operation. Reusing a key with the same device/artifact returns the original operation. Usage: operation, err := sdk.AssignApplication(ctx, scope, deviceID, digest, requestKey, 24*time.Hour).

*SDK.ListOperations

go/applications.go:85

// ListOperations returns durable scoped progress, failures and observed installation results.
// Usage: operations, err := sdk.ListOperations(ctx, scope, deviceID, "", 100).
func (s *SDK) ListOperations(ctx context.Context, scope, device, after string, limit int) ([]Operation, error)

ListOperations returns durable scoped progress, failures and observed installation results. Usage: operations, err := sdk.ListOperations(ctx, scope, deviceID, "", 100).

*SDK.RemoveApplication

go/applications.go:102

// RemoveApplication removes unreferenced scoped catalog metadata. Content bytes
// are retained: deleting shared files concurrently with registrations is unsafe.
// Usage: err := sdk.RemoveApplication(ctx, scope, digest).
func (s *SDK) RemoveApplication(ctx context.Context, scope, digest string) error

RemoveApplication removes unreferenced scoped catalog metadata. Content bytes are retained: deleting shared files concurrently with registrations is unsafe. Usage: err := sdk.RemoveApplication(ctx, scope, digest).

ErrCursorExpired

go/changes.go:15

var ErrCursorExpired = ports.ErrCursorExpired

Change

go/changes.go:21

type Change struct {
    Sequence    uint64
    Kind        string
    ResourceID  string
}

Change is a durable scoped invalidation or application tombstone, without tokens or raw state. Refresh device_changed through GetDeviceState; application_changed through GetApplication. group_changed/fleet_changed require GetGroup/GetFleetAssignment. application_removed deletes that digest from the host projection. Sequence is strictly ascending per scope.

ChangePage

go/changes.go:29

type ChangePage struct {
    Items   []Change
    Cursor  string
    More    bool
}

ChangePage returns a checkpoint even when no records exist. Persist it with host projection updates; failures may replay a batch and must be handled idempotently. Changes are retained for 10,000 records per scope.

DesiredApplication

go/changes.go:36

type DesiredApplication struct {
    Artifact    Artifact    `json:"artifact"`
    Revision    uint64      `json:"revision"`
}

DesiredApplication is a host-facing verified desired package and revision.

DeviceState

go/changes.go:43

type DeviceState struct {
    Network     NetworkStatus       `json:"network"`
    Device      Device          `json:"device"`
    Desired     []DesiredApplication    `json:"desired"`
    Operations  []Operation     `json:"operations"`
    Commands    []Command       `json:"commands"`
    Policy      PolicyStatus        `json:"policy"`
}

DeviceState is a consistent scoped projection, including complete operation history and desired/observed policy. Reading does not expire operations or trigger effects; deadline-aware reads use GetOperation/QueryOperations.

ProjectionItem

go/changes.go:53

type ProjectionItem struct {
    Device      *DeviceState        `json:"device,omitempty"`
    Application *Artifact       `json:"application,omitempty"`
    Group       *Group          `json:"group,omitempty"`
    Fleet       *FleetAssignment    `json:"fleet,omitempty"`
}

ProjectionItem is one snapshot resource: exactly one pointer is populated.

ProjectionPage

go/changes.go:63

type ProjectionPage struct {
    Items       []ProjectionItem
    NextCursor  string
    ChangesCursor   string
    ExpiresAt   time.Time
}

ProjectionPage contains immutable scoped records. Build a staged projection across all pages, atomically replace the old projection, then use ChangesCursor after the final page. NextCursor expires after fifteen minutes or when this scope starts four newer scans.

*SDK.ListChanges

go/changes.go:118

// ListChanges reads a replayable bounded scope log. Empty cursor starts at sequence zero;
// ErrCursorExpired requires a consistent ReadProjection, never silently skipping missed changes.
// Hosts authorize the scope on every call; callbacks are only optional wakeups, not durable delivery.
// Usage: page, err := sdk.ListChanges(ctx, scope, savedCursor, 100).
func (s *SDK) ListChanges(ctx context.Context, scope, cursor string, limit int) (ChangePage, error)

ListChanges reads a replayable bounded scope log. Empty cursor starts at sequence zero; ErrCursorExpired requires a consistent ReadProjection, never silently skipping missed changes. Hosts authorize the scope on every call; callbacks are only optional wakeups, not durable delivery. Usage: page, err := sdk.ListChanges(ctx, scope, savedCursor, 100).

*SDK.GetDeviceState

go/changes.go:143

// GetDeviceState reads a transactionally consistent scoped aggregate without exposing agent lease tokens.
// Usage: state, err := sdk.GetDeviceState(ctx, scope, deviceID).
func (s *SDK) GetDeviceState(ctx context.Context, scope, id string) (DeviceState, error)

GetDeviceState reads a transactionally consistent scoped aggregate without exposing agent lease tokens. Usage: state, err := sdk.GetDeviceState(ctx, scope, deviceID).

*SDK.GetApplication

go/changes.go:159

// GetApplication reads one scoped verified catalog entry; absent/foreign digests both return ErrNotFound.
// Usage: artifact, err := sdk.GetApplication(ctx, scope, digest).
func (s *SDK) GetApplication(ctx context.Context, scope, digest string) (Artifact, error)

GetApplication reads one scoped verified catalog entry; absent/foreign digests both return ErrNotFound. Usage: artifact, err := sdk.GetApplication(ctx, scope, digest).

*SDK.ReadProjection

go/changes.go:177

// ReadProjection starts or continues an immutable scoped snapshot and matching change watermark.
// Cursor "" starts a new scan. Complete all pages before committing ChangesCursor; expiry/eviction
// returns ErrCursorExpired and requires discarding the staged scan. Never combine pages from different scans.
// Usage: page, err := sdk.ReadProjection(ctx, scope, "", 100).
func (s *SDK) ReadProjection(ctx context.Context, scope, cursor string, limit int) (ProjectionPage, error)

ReadProjection starts or continues an immutable scoped snapshot and matching change watermark. Cursor "" starts a new scan. Complete all pages before committing ChangesCursor; expiry/eviction returns ErrCursorExpired and requires discarding the staged scan. Never combine pages from different scans. Usage: page, err := sdk.ReadProjection(ctx, scope, "", 100).

ErrUnsupported

go/commands.go:11

var ErrUnsupported = ports.ErrUnsupported

CommandKind

go/commands.go:14

type CommandKind string

CommandKind selects a one-shot Device Owner action, subject to platform capability and observed outcome.

CommandReboot

go/commands.go:17

const CommandReboot CommandKind = "REBOOT"

CommandLock

go/commands.go:18

const CommandLock CommandKind = "LOCK"

CommandObservation

go/commands.go:22

type CommandObservation = ports.CommandObservation

CommandObservation is platform readback, not proof of who caused a reboot or cryptographic device attestation.

Command

go/commands.go:26

type Command struct {
    ID      string          `json:"id"`
    DeviceID    string          `json:"device_id"`
    Kind        CommandKind     `json:"kind"`
    State       string          `json:"state"`
    Deadline    time.Time       `json:"deadline"`
    ErrorCode   string          `json:"error_code,omitempty"`
    Observation *CommandObservation `json:"observation,omitempty"`
}

Command exposes a one-shot lifecycle without the agent's dispatch credential. UNCERTAIN requires an explicit host decision; retrying the same key never schedules another action.

CommandPage

go/commands.go:37

type CommandPage struct {
    Items       []Command
    NextCursor  string
}

CommandPage contains a live ascending-ID history page for one authorized device.

*SDK.SubmitCommand

go/commands.go:46

// SubmitCommand queues reboot or lock only when the device advertises the corresponding Device Owner capability.
// A stable key binds device/kind; its original deadline is retained on retry (timeout 1m–7d).
// Reboot success needs a boot-count increase; lock success needs a configured secure lock and locked readback.
// Usage: command, err := sdk.SubmitCommand(ctx, scope, deviceID, kylok.CommandReboot, "maintenance", time.Hour).
func (s *SDK) SubmitCommand(ctx context.Context, scope, device string, kind CommandKind, key string, timeout time.Duration) (Command, error)

SubmitCommand queues reboot or lock only when the device advertises the corresponding Device Owner capability. A stable key binds device/kind; its original deadline is retained on retry (timeout 1m–7d). Reboot success needs a boot-count increase; lock success needs a configured secure lock and locked readback. Usage: command, err := sdk.SubmitCommand(ctx, scope, deviceID, kylok.CommandReboot, "maintenance", time.Hour).

*SDK.GetCommand

go/commands.go:64

// GetCommand reads an authorized device's one-shot outcome; overdue delivered actions are UNCERTAIN, never replayed.
// Usage: command, err := sdk.GetCommand(ctx, scope, deviceID, commandID).
func (s *SDK) GetCommand(ctx context.Context, scope, device, id string) (Command, error)

GetCommand reads an authorized device's one-shot outcome; overdue delivered actions are UNCERTAIN, never replayed. Usage: command, err := sdk.GetCommand(ctx, scope, deviceID, commandID).

*SDK.QueryCommands

go/commands.go:77

// QueryCommands reads bounded command history with a scope/device-bound cursor; it never triggers a platform action.
// Usage: page, err := sdk.QueryCommands(ctx, scope, deviceID, PageRequest{Limit:20}).
func (s *SDK) QueryCommands(ctx context.Context, scope, device string, page PageRequest) (CommandPage, error)

QueryCommands reads bounded command history with a scope/device-bound cursor; it never triggers a platform action. Usage: page, err := sdk.QueryCommands(ctx, scope, deviceID, PageRequest{Limit:20}).

*SDK.CancelCommand

go/commands.go:107

// CancelCommand cancels queued work; committed delivery becomes UNCERTAIN until a valid platform result resolves it.
// Cancellation cannot undo a delivered reboot/lock, and never schedules a replacement action.
// Usage: command, err := sdk.CancelCommand(ctx, scope, deviceID, commandID).
func (s *SDK) CancelCommand(ctx context.Context, scope, device, id string) (Command, error)

CancelCommand cancels queued work; committed delivery becomes UNCERTAIN until a valid platform result resolves it. Cancellation cannot undo a delivered reboot/lock, and never schedules a replacement action. Usage: command, err := sdk.CancelCommand(ctx, scope, deviceID, commandID).

Event

go/events.go:12

type Event struct {
    ID      string      `json:"id"`
    Kind        string      `json:"kind"`
    ScopeID     string      `json:"scope_id"`
    DeviceID    string      `json:"device_id"`
    Revision    uint64      `json:"revision"`
    At      time.Time   `json:"at"`
}

Event contains identifiers and committed revisions, never tokens, credentials, enrollment keys, QR contents or raw inventory. ID is stable across RPC retries.

EventSink

go/events.go:25

type EventSink func(context.Context, Event) error

EventSink is an optional best-effort notification hook. Calls are serialized on one SDK-owned worker and must honor cancellation. Errors/panics never change committed results. Delivery can be dropped, duplicated, or lost on shutdown; use ListChanges/ReadProjection for durable projection recovery and export permanent audit records to host storage before retention expires.

Group

go/fleet.go:14

type Group = ports.Group

Group is an opaque scoped membership set, capped at 100 devices; it carries no business metadata.

FleetRequest

go/fleet.go:18

type FleetRequest = ports.FleetRequest

FleetRequest selects one group or an explicit device set with an absolute deployment window. Request ID is the scope-local retry key; membership freezes on creation.

FleetItem

go/fleet.go:21

type FleetItem = ports.FleetItem

FleetItem describes submission progress; use OperationID to read the device's observed execution result.

FleetAssignment

go/fleet.go:24

type FleetAssignment = ports.FleetAssignment

FleetAssignment is a detached durable fan-out checkpoint, not a claim that devices applied its APK.

GroupPage

go/fleet.go:27

type GroupPage struct {
    Items       []Group
    NextCursor  string
}

GroupPage contains a live ascending-ID membership page and a scope-bound continuation.

FleetPage

go/fleet.go:33

type FleetPage struct {
    Items       []FleetAssignment
    NextCursor  string
}

FleetPage contains durable assignment checkpoints; hosts scan these to resume incomplete work after restart.

*SDK.ReplaceGroup

go/fleet.go:57

// ReplaceGroup replaces the complete membership using optimistic concurrency (zero creates).
// An identical retry with the same expected revision returns the committed set; foreign/revoked members fail.
// Existing fleet assignments keep their frozen targets. An empty set clears membership.
// Usage: group, err := sdk.ReplaceGroup(ctx, scope, "lobby", []string{deviceID}, 0).
func (s *SDK) ReplaceGroup(ctx context.Context, scope, id string, devices []string, expectedRevision uint64) (Group, error)

ReplaceGroup replaces the complete membership using optimistic concurrency (zero creates). An identical retry with the same expected revision returns the committed set; foreign/revoked members fail. Existing fleet assignments keep their frozen targets. An empty set clears membership. Usage: group, err := sdk.ReplaceGroup(ctx, scope, "lobby", []string{deviceID}, 0).

*SDK.GetGroup

go/fleet.go:73

// GetGroup reads membership in one authorized scope; foreign and absent IDs both return ErrNotFound.
// Usage: group, err := sdk.GetGroup(ctx, scope, "lobby").
func (s *SDK) GetGroup(ctx context.Context, scope, id string) (Group, error)

GetGroup reads membership in one authorized scope; foreign and absent IDs both return ErrNotFound. Usage: group, err := sdk.GetGroup(ctx, scope, "lobby").

*SDK.QueryGroups

go/fleet.go:85

// QueryGroups reads a bounded live membership page. Hosts authorize the scope on every call.
// Usage: page, err := sdk.QueryGroups(ctx, scope, PageRequest{Limit:20}).
func (s *SDK) QueryGroups(ctx context.Context, scope string, page PageRequest) (GroupPage, error)

QueryGroups reads a bounded live membership page. Hosts authorize the scope on every call. Usage: page, err := sdk.QueryGroups(ctx, scope, PageRequest{Limit:20}).

*SDK.ScheduleApplication

go/fleet.go:113

// ScheduleApplication creates one durable install with an absolute [notBefore, deadline) window (at most seven days).
// The same key binds artifact and window exactly. The latest committed assignment wins per package;
// cancellation/supersession cannot undo an already delivered platform effect. Expired retries still read the original.
// Usage: op, err := sdk.ScheduleApplication(ctx, scope, deviceID, digest, "nightly", start, start.Add(time.Hour)).
func (s *SDK) ScheduleApplication(ctx context.Context, scope, device, digest, key string, notBefore, deadline time.Time) (Operation, error)

ScheduleApplication creates one durable install with an absolute [notBefore, deadline) window (at most seven days). The same key binds artifact and window exactly. The latest committed assignment wins per package; cancellation/supersession cannot undo an already delivered platform effect. Expired retries still read the original. Usage: op, err := sdk.ScheduleApplication(ctx, scope, deviceID, digest, "nightly", start, start.Add(time.Hour)).

*SDK.CreateFleetAssignment

go/fleet.go:133

// CreateFleetAssignment freezes up to 100 targets without submitting device work. Set GroupID or DeviceIDs, never both.
// Reusing ID requires the same selector, APK and absolute window. Group edits do not expand retries.
// Hosts drive AdvanceFleetAssignment and retain a scan/checkpoint for their authorized scopes.
// Usage: batch, err := sdk.CreateFleetAssignment(ctx, FleetRequest{ScopeID:scope, ID:"nightly", GroupID:"lobby", ArtifactSHA256:digest, NotBefore:start, Deadline:start.Add(time.Hour)}).
func (s *SDK) CreateFleetAssignment(ctx context.Context, request FleetRequest) (FleetAssignment, error)

CreateFleetAssignment freezes up to 100 targets without submitting device work. Set GroupID or DeviceIDs, never both. Reusing ID requires the same selector, APK and absolute window. Group edits do not expand retries. Hosts drive AdvanceFleetAssignment and retain a scan/checkpoint for their authorized scopes. Usage: batch, err := sdk.CreateFleetAssignment(ctx, FleetRequest{ScopeID:scope, ID:"nightly", GroupID:"lobby", ArtifactSHA256:digest, NotBefore:start, Deadline:start.Add(time.Hour)}).

*SDK.GetFleetAssignment

go/fleet.go:152

// GetFleetAssignment reads frozen targets and per-device submission results, without advancing work.
// Usage: batch, err := sdk.GetFleetAssignment(ctx, scope, "nightly").
func (s *SDK) GetFleetAssignment(ctx context.Context, scope, id string) (FleetAssignment, error)

GetFleetAssignment reads frozen targets and per-device submission results, without advancing work. Usage: batch, err := sdk.GetFleetAssignment(ctx, scope, "nightly").

*SDK.QueryFleetAssignments

go/fleet.go:164

// QueryFleetAssignments scans durable checkpoints so host workers can resume pending fan-out after restart.
// Usage: page, err := sdk.QueryFleetAssignments(ctx, scope, PageRequest{Limit:20}).
func (s *SDK) QueryFleetAssignments(ctx context.Context, scope string, page PageRequest) (FleetPage, error)

QueryFleetAssignments scans durable checkpoints so host workers can resume pending fan-out after restart. Usage: page, err := sdk.QueryFleetAssignments(ctx, scope, PageRequest{Limit:20}).

*SDK.AdvanceFleetAssignment

go/fleet.go:192

// AdvanceFleetAssignment atomically submits at most limit pending targets (1–100); permanent per-device errors are retained.
// Infrastructure/context failures roll back the chunk. Concurrent workers and lost responses cannot create duplicate work.
// Complete means fan-out finished; read each OperationID for installation/compliance results.
// Usage: batch, err := sdk.AdvanceFleetAssignment(ctx, scope, "nightly", 20).
func (s *SDK) AdvanceFleetAssignment(ctx context.Context, scope, id string, limit int) (FleetAssignment, error)

AdvanceFleetAssignment atomically submits at most limit pending targets (1–100); permanent per-device errors are retained. Infrastructure/context failures roll back the chunk. Concurrent workers and lost responses cannot create duplicate work. Complete means fan-out finished; read each OperationID for installation/compliance results. Usage: batch, err := sdk.AdvanceFleetAssignment(ctx, scope, "nightly", 20).

*SDK.CancelFleetAssignment

go/fleet.go:205

// CancelFleetAssignment cancels pending targets and stops future dispatch for active submitted operations.
// Completed/superseded operations are preserved; already delivered Android effects may still complete.
// Usage: batch, err := sdk.CancelFleetAssignment(ctx, scope, "nightly").
func (s *SDK) CancelFleetAssignment(ctx context.Context, scope, id string) (FleetAssignment, error)

CancelFleetAssignment cancels pending targets and stops future dispatch for active submitted operations. Completed/superseded operations are preserved; already delivered Android effects may still complete. Usage: batch, err := sdk.CancelFleetAssignment(ctx, scope, "nightly").

*SDK.CancelOperation

go/fleet.go:219

// CancelOperation stops future dispatch/download and signals the agent to abandon uncommitted local work.
// CANCELLED does not prove that a delivered installation stopped. Desired intent stays recorded;
// no implicit uninstall/rollback or drift retry follows. Reassign with a new key to resume.
// Usage: op, err := sdk.CancelOperation(ctx, scope, deviceID, operationID).
func (s *SDK) CancelOperation(ctx context.Context, scope, device, id string) (Operation, error)

CancelOperation stops future dispatch/download and signals the agent to abandon uncommitted local work. CANCELLED does not prove that a delivered installation stopped. Desired intent stays recorded; no implicit uninstall/rollback or drift retry follows. Reassign with a new key to resume. Usage: op, err := sdk.CancelOperation(ctx, scope, deviceID, operationID).

Options

go/kylok.go:38

type Options struct {
    // HTTP/HTTPS origin advertised to devices; it does not bind or start a listener.
    PublicURL   string
    // Signed DPC APK verified by provisioning.Inspect.
    Bootstrap   *provisioning.APK
    // Persistent default database/artifact directory; unnecessary when both providers are supplied.
    DataDir string
    // Optional concurrent transactional provider; never replaced with an in-memory fallback on failure.
    Store   ports.StateStore
    // Optional immutable content provider; must preserve the ArtifactStore integrity contract.
    Artifacts   ports.ArtifactStore
    // Explicit opt-in for local provisioning proofs; disabled for normal hosts.
    AllowDebugAPK   bool
    // Optional wall clock for deterministic expiry/deadline checks; defaults to time.Now.
    Clock   func() time.Time
    // Optional APK origin. Defaults to PublicURL; independently supports HTTP/HTTPS
    // and domain/IP hosts. Mount BootstrapHandler on a separate origin as needed.
    BootstrapURL    string
    // Optional sanitized best-effort committed-event sink; see EventSink for cancellation/delivery rules.
    Events  EventSink
    // Optional host-owned resolver for immutable scoped Wi-Fi passphrase versions. Required for protected profiles.
    NetworkSecrets  ports.NetworkSecretProvider
    // Per callback; defaults to one second, at most 30 seconds. A non-cooperative
    // host callback can stall only its one worker, never authentication or sync.
    EventTimeout    time.Duration
}

Options configures one embeddable SDK. Supply verified bootstrap content and a device-reachable origin; durable defaults use DataDir. Supplied providers remain host-owned.

SDK

go/kylok.go:67

type SDK struct {
    // contains filtered or unexported fields
}

SDK owns the management facade and agent handlers. Hosts own authorization and listeners, drain requests before Close, and close their own supplied providers.

Enrollment

go/kylok.go:82

type Enrollment struct {
    CorrelationID   string
    Token       string
    ScopeID     string
    ExpiresAt   time.Time
}

New

go/kylok.go:98

// New validates options/current storage schema and registers the verified APK.
// It starts no listeners. An optional event sink uses one bounded SDK worker.
// The host owns TLS, authorization, supplied providers and shutdown.
// Custom providers remain host-owned even if construction fails.
// Usage: sdk, err := kylok.New(ctx, kylok.Options{PublicURL: origin, Bootstrap: apk, DataDir: dataDir}).
func New(ctx context.Context, o Options) (_ *SDK, err error)

New validates options/current storage schema and registers the verified APK. It starts no listeners. An optional event sink uses one bounded SDK worker. The host owns TLS, authorization, supplied providers and shutdown. Custom providers remain host-owned even if construction fails. Usage: sdk, err := kylok.New(ctx, kylok.Options{PublicURL: origin, Bootstrap: apk, DataDir: dataDir}).

*SDK.Close

go/kylok.go:182

// Close cancels SDK-owned notifications and storage exactly once; supplied providers remain host-owned.
// Usage: defer sdk.Close() after draining host listeners; hosts close supplied stores separately.
func (s *SDK) Close() error

Close cancels SDK-owned notifications and storage exactly once; supplied providers remain host-owned. Usage: defer sdk.Close() after draining host listeners; hosts close supplied stores separately.

*SDK.CreateEnrollment

go/kylok.go:207

// CreateEnrollment creates a single-use token bound to the authorized scope and current verified DPC APK.
// Usage: enrollment, err := sdk.CreateEnrollment(ctx, scope, 15*time.Minute).
func (s *SDK) CreateEnrollment(ctx context.Context, scope string, ttl time.Duration) (Enrollment, error)

CreateEnrollment creates a single-use token bound to the authorized scope and current verified DPC APK. Usage: enrollment, err := sdk.CreateEnrollment(ctx, scope, 15*time.Minute).

*SDK.CreateEnrollmentWithOptions

go/kylok.go:216

// CreateEnrollmentWithOptions creates an opaque correlation binding and a private single-use token.
// Nonempty correlation IDs are unique in their scope, including after consumption/expiry.
// Duplicate creation returns ErrConflict, never the original token. If the creation response
// is lost, use a new correlation ID and let the unclaimed token expire; no read exposes it.
// Usage: e, err := sdk.CreateEnrollmentWithOptions(ctx, EnrollmentOptions{ScopeID: scope, TTL: 15*time.Minute, CorrelationID: requestID}).
func (s *SDK) CreateEnrollmentWithOptions(ctx context.Context, input EnrollmentOptions) (Enrollment, error)

CreateEnrollmentWithOptions creates an opaque correlation binding and a private single-use token. Nonempty correlation IDs are unique in their scope, including after consumption/expiry. Duplicate creation returns ErrConflict, never the original token. If the creation response is lost, use a new correlation ID and let the unclaimed token expire; no read exposes it. Usage: e, err := sdk.CreateEnrollmentWithOptions(ctx, EnrollmentOptions{ScopeID: scope, TTL: 15*time.Minute, CorrelationID: requestID}).

*SDK.QR

go/kylok.go:237

// QR renders private provisioning JSON using this host's configured API and bootstrap origins.
// Usage: payload, err := sdk.QR(ctx, enrollment.Token); keep the returned JSON private.
func (s *SDK) QR(ctx context.Context, token string) ([]byte, error)

QR renders private provisioning JSON using this host's configured API and bootstrap origins. Usage: payload, err := sdk.QR(ctx, enrollment.Token); keep the returned JSON private.

*SDK.QRWithOrigins

go/kylok.go:245

// QRWithOrigins issues the same verified enrollment through host-selected API
// and APK origins, for example another bound LAN interface or a custom domain.
// Changing a QR does not change an already enrolled device's endpoint.
// Usage: payload, err := sdk.QRWithOrigins(ctx, token, "http://192.168.1.5:8080", "http://192.168.1.5:8080").
func (s *SDK) QRWithOrigins(ctx context.Context, token, apiOrigin, bootstrapOrigin string) ([]byte, error)

QRWithOrigins issues the same verified enrollment through host-selected API and APK origins, for example another bound LAN interface or a custom domain. Changing a QR does not change an already enrolled device's endpoint. Usage: payload, err := sdk.QRWithOrigins(ctx, token, "http://192.168.1.5:8080", "http://192.168.1.5:8080").

*SDK.ListDevices

go/kylok.go:274

// ListDevices and RevokeDevice are in-process management APIs. Hosts must authorize
// the business user and scope before invoking them; no remote management route exists.
// Usage: devices, err := sdk.ListDevices(ctx, scope, "", 100).
func (s *SDK) ListDevices(ctx context.Context, scope, after string, limit int) ([]Device, error)

ListDevices and RevokeDevice are in-process management APIs. Hosts must authorize the business user and scope before invoking them; no remote management route exists. Usage: devices, err := sdk.ListDevices(ctx, scope, "", 100).

*SDK.RevokeDevice

go/kylok.go:290

// RevokeDevice rejects future authenticated activity and recovery for one authorized scope/device.
// Usage: err := sdk.RevokeDevice(ctx, scope, deviceID).
func (s *SDK) RevokeDevice(ctx context.Context, scope, id string) error

RevokeDevice rejects future authenticated activity and recovery for one authorized scope/device. Usage: err := sdk.RevokeDevice(ctx, scope, deviceID).

*SDK.Handler

go/kylok.go:308

// Handler exposes agent RPCs, public bootstrap APKs and authorized managed APKs,
// never administrator routes. Hosts enable HTTP/2 (including h2c for HTTP). TLS
// is required for HTTPS origins; forwarded TLS headers are not trusted.
// Usage: server.Handler = sdk.Handler(); enable HTTP/2 and drain the listener before sdk.Close().
func (s *SDK) Handler() http.Handler

Handler exposes agent RPCs, public bootstrap APKs and authorized managed APKs, never administrator routes. Hosts enable HTTP/2 (including h2c for HTTP). TLS is required for HTTPS origins; forwarded TLS headers are not trusted. Usage: server.Handler = sdk.Handler(); enable HTTP/2 and drain the listener before sdk.Close().

*SDK.BootstrapHandler

go/kylok.go:331

// BootstrapHandler serves only immutable APKs, never agent/management routes or QR secrets.
// It follows the selected BootstrapURL scheme, independently of the API origin.
// Usage: bootstrapServer.Handler = sdk.BootstrapHandler().
func (s *SDK) BootstrapHandler() http.Handler

BootstrapHandler serves only immutable APKs, never agent/management routes or QR secrets. It follows the selected BootstrapURL scheme, independently of the API origin. Usage: bootstrapServer.Handler = sdk.BootstrapHandler().

ErrInvalidArgument

go/management.go:23

var ErrInvalidArgument = ports.ErrInvalidArgument

Management errors support errors.Is independently of transport and persistence adapters.

ErrNotFound

go/management.go:24

var ErrNotFound = ports.ErrNotFound

Management errors support errors.Is independently of transport and persistence adapters.

ErrConflict

go/management.go:25

var ErrConflict = ports.ErrConflict

Management errors support errors.Is independently of transport and persistence adapters.

ErrExpired

go/management.go:26

var ErrExpired = ports.ErrExpired

Management errors support errors.Is independently of transport and persistence adapters.

ErrReferenced

go/management.go:27

var ErrReferenced = ports.ErrReferenced

Management errors support errors.Is independently of transport and persistence adapters.

ErrConsumed

go/management.go:28

var ErrConsumed = ports.ErrConsumed

Management errors support errors.Is independently of transport and persistence adapters.

ErrRecoveryExpired

go/management.go:29

var ErrRecoveryExpired = ports.ErrRecoveryExpired

Management errors support errors.Is independently of transport and persistence adapters.

ErrRevoked

go/management.go:30

var ErrRevoked = ports.ErrRevoked

Management errors support errors.Is independently of transport and persistence adapters.

ErrUnauthorized

go/management.go:31

var ErrUnauthorized = ports.ErrUnauthorized

Management errors support errors.Is independently of transport and persistence adapters.

ErrStale

go/management.go:32

var ErrStale = ports.ErrStale

Management errors support errors.Is independently of transport and persistence adapters.

ErrClosed

go/management.go:33

var ErrClosed = errors.New("SDK closed")

Management errors support errors.Is independently of transport and persistence adapters.

EnrollmentOptions

go/management.go:38

type EnrollmentOptions struct {
    ScopeID     string
    TTL     time.Duration
    CorrelationID   string
}

EnrollmentOptions binds a private token to an authorized scope and optional opaque host correlation. CorrelationID is association metadata, never authorization; it must not contain secrets.

Device

go/management.go:45

type Device struct {
    ID          string      `json:"id"`
    ScopeID         string      `json:"scope_id"`
    CorrelationID       string      `json:"correlation_id,omitempty"`
    State           string      `json:"state"`
    Inventory       Inventory   `json:"inventory"`
    CreatedAt       time.Time   `json:"created_at"`
    LastSeenAt      time.Time   `json:"last_seen_at"`
    DesiredRevision     uint64      `json:"desired_revision"`
    ReportedRevision    uint64      `json:"reported_revision"`
}

Device is a detached host-facing identity and observation. CorrelationID is host-only association metadata.

Inventory

go/management.go:58

type Inventory struct {
    APILevel        uint32          `json:"api_level"`
    Model           string          `json:"model"`
    BuildFingerprint    string          `json:"build_fingerprint"`
    AgentVersion        string          `json:"agent_version"`
    DeviceOwner     bool            `json:"device_owner"`
    Capabilities        []string        `json:"capabilities"`
    Applications        []InstalledApplication  `json:"applications"`
    SupportedABIs       []string        `json:"supported_abis"`
}

Inventory contains device-reported observations, not attestation or a firmware support guarantee.

InstalledApplication

go/management.go:70

type InstalledApplication struct {
    PackageName     string      `json:"package_name"`
    VersionCode     int64       `json:"version_code"`
    SigningCertificates []string    `json:"signing_certificates"`
}

InstalledApplication identifies an observed package version and signing certificates.

Artifact

go/management.go:77

type Artifact struct {
    ScopeID         string      `json:"scope_id"`
    SHA256          string      `json:"sha256"`
    PackageName     string      `json:"package_name"`
    VersionCode     int64       `json:"version_code"`
    MinSDK          uint32      `json:"min_sdk"`
    MaxSDK          uint32      `json:"max_sdk"`
    SigningCertificates []string    `json:"signing_certificates"`
    SupportedABIs       []string    `json:"supported_abis"`
    SizeBytes       int64       `json:"size_bytes"`
}

Artifact is immutable verified application metadata, with no storage location or download credentials.

Operation

go/management.go:90

type Operation struct {
    ID      string          `json:"id"`
    DeviceID    string          `json:"device_id"`
    Artifact    Artifact        `json:"artifact"`
    Revision    uint64          `json:"revision"`
    State       string          `json:"state"`
    NotBefore   time.Time       `json:"not_before"`
    Deadline    time.Time       `json:"deadline"`
    DownloadedBytes int64           `json:"downloaded_bytes"`
    ErrorCode   string          `json:"error_code"`
    ErrorMessage    string          `json:"error_message"`
    Observed    *InstalledApplication   `json:"observed,omitempty"`
}

Operation exposes durable progress/results without agent lease tokens or report checkpoint internals.

DeviceFilter

go/management.go:105

type DeviceFilter struct {
    State       string
    CorrelationID   string
}

DeviceFilter selects exact state/correlation matches within one authorized scope.

OperationFilter

go/management.go:111

type OperationFilter struct{ State string }

OperationFilter selects an exact operation state for one scoped device.

PageRequest

go/management.go:115

type PageRequest struct {
    Cursor  string
    Limit   int
}

PageRequest selects a live ascending-ID page; zero Limit defaults to 20, and the maximum is 100. Cursor is opaque and bound to the scope/device/filter; authorization is still required on every request.

DevicePage

go/management.go:121

type DevicePage struct {
    Items       []Device
    NextCursor  string
}

DevicePage returns detached observations and a cursor only when more matching results exist.

OperationPage

go/management.go:127

type OperationPage struct {
    Items       []Operation
    NextCursor  string
}

OperationPage returns detached progress/results and a cursor only when more matching results exist.

*SDK.Ready

go/management.go:156

// Ready checks current backend/bootstrap availability without mutating state or starting a listener.
// Drain host handlers before Close. Supplied providers remain host-owned and readiness is a point-in-time observation.
// Usage: if err := sdk.Ready(ctx); err != nil { respondUnavailable(err) }.
func (s *SDK) Ready(ctx context.Context) error

Ready checks current backend/bootstrap availability without mutating state or starting a listener. Drain host handlers before Close. Supplied providers remain host-owned and readiness is a point-in-time observation. Usage: if err := sdk.Ready(ctx); err != nil { respondUnavailable(err) }.

*SDK.GetDevice

go/management.go:175

// GetDevice reads one identity in an authorized scope; absent and foreign identities both return ErrNotFound.
// Usage: device, err := sdk.GetDevice(ctx, scope, deviceID).
func (s *SDK) GetDevice(ctx context.Context, scope, id string) (Device, error)

GetDevice reads one identity in an authorized scope; absent and foreign identities both return ErrNotFound. Usage: device, err := sdk.GetDevice(ctx, scope, deviceID).

*SDK.GetOperation

go/management.go:189

// GetOperation reads scoped durable progress and expires overdue work; it never exposes a download lease.
// Absent, foreign-scope and foreign-device operations all return ErrNotFound.
// Usage: operation, err := sdk.GetOperation(ctx, scope, deviceID, operationID).
func (s *SDK) GetOperation(ctx context.Context, scope, device, id string) (Operation, error)

GetOperation reads scoped durable progress and expires overdue work; it never exposes a download lease. Absent, foreign-scope and foreign-device operations all return ErrNotFound. Usage: operation, err := sdk.GetOperation(ctx, scope, deviceID, operationID).

*SDK.QueryDevices

go/management.go:249

// QueryDevices reads a live keyset page with exact optional filters. Concurrent inserts behind
// the cursor or mutable filter changes require a new scan; this is not a frozen snapshot.
// Usage: page, err := sdk.QueryDevices(ctx, scope, DeviceFilter{CorrelationID: requestID}, PageRequest{Limit: 20}).
func (s *SDK) QueryDevices(ctx context.Context, scope string, filter DeviceFilter, page PageRequest) (DevicePage, error)

QueryDevices reads a live keyset page with exact optional filters. Concurrent inserts behind the cursor or mutable filter changes require a new scan; this is not a frozen snapshot. Usage: page, err := sdk.QueryDevices(ctx, scope, DeviceFilter{CorrelationID: requestID}, PageRequest{Limit: 20}).

*SDK.QueryOperations

go/management.go:276

// QueryOperations reads a live operation page for one authorized device; expiry is evaluated on each read.
// Usage: page, err := sdk.QueryOperations(ctx, scope, deviceID, OperationFilter{State: "SUCCEEDED"}, PageRequest{Limit: 20}).
func (s *SDK) QueryOperations(ctx context.Context, scope, device string, filter OperationFilter, page PageRequest) (OperationPage, error)

QueryOperations reads a live operation page for one authorized device; expiry is evaluated on each read. Usage: page, err := sdk.QueryOperations(ctx, scope, deviceID, OperationFilter{State: "SUCCEEDED"}, PageRequest{Limit: 20}).

ErrNetworkSecretUnavailable

go/network.go:20

var ErrNetworkSecretUnavailable = errors.New("network secret unavailable")

ErrNetworkSecretUnavailable hides provider diagnostics so credential values cannot leak through SDK errors.

NetworkPolicy

go/network.go:23

type NetworkPolicy = ports.NetworkPolicy

NetworkPolicy owns managed saved Wi-Fi profiles and private CAs; an empty document releases managed resources safely.

WifiProfile

go/network.go:26

type WifiProfile = ports.WifiProfile

WifiProfile uses a scoped immutable SecretRef; no management read contains a delivered password.

CACertificate

go/network.go:29

type CACertificate = ports.CACertificate

CACertificate carries a CA's DER bytes, without its private key.

DesiredNetworkPolicy

go/network.go:32

type DesiredNetworkPolicy = ports.DesiredNetworkPolicy

DesiredNetworkPolicy binds normalized references and CA ownership to a desired revision.

NetworkReport

go/network.go:35

type NetworkReport = ports.NetworkReport

NetworkReport separates authenticated route verification from association/setter results.

NetworkStatus

go/network.go:38

type NetworkStatus = ports.NetworkStatus

NetworkStatus keeps desired and reported state distinct and excludes resolved network secrets.

NetworkSecretProvider

go/network.go:41

type NetworkSecretProvider = ports.NetworkSecretProvider

NetworkSecretProvider is a host-owned immutable scoped vault contract; rotate using a new reference version.

*SDK.SetNetworkPolicy

go/network.go:47

// SetNetworkPolicy replaces bounded managed networks/trust. Hosts supply immutable passphrase versions through NetworkSecrets.
// Android requires permissions, an independently verified saved recovery network and ownership readback before mutation.
// A failed migration/release retains the working route; a new request key creates the host's retry revision.
// Usage: desired, err := sdk.SetNetworkPolicy(ctx, scope, deviceID, "network-v2", kylok.NetworkPolicy{PrimaryID:"office", Profiles:[]kylok.WifiProfile{{ID:"office",SSID:"Office",Security:"WPA2_PSK",SecretRef:"office-key-v2"}}}).
func (s *SDK) SetNetworkPolicy(ctx context.Context, scope, device, key string, input NetworkPolicy) (DesiredNetworkPolicy, error)

SetNetworkPolicy replaces bounded managed networks/trust. Hosts supply immutable passphrase versions through NetworkSecrets. Android requires permissions, an independently verified saved recovery network and ownership readback before mutation. A failed migration/release retains the working route; a new request key creates the host's retry revision. Usage: desired, err := sdk.SetNetworkPolicy(ctx, scope, deviceID, "network-v2", kylok.NetworkPolicy{PrimaryID:"office", Profiles:[]kylok.WifiProfile{{ID:"office",SSID:"Office",Security:"WPA2_PSK",SecretRef:"office-key-v2"}}}).

*SDK.GetNetworkPolicy

go/network.go:96

// GetNetworkPolicy returns reference-only desired/report/compliance state in the authorized scope.
// Usage: status, err := sdk.GetNetworkPolicy(ctx, scope, deviceID).
func (s *SDK) GetNetworkPolicy(ctx context.Context, scope, device string) (NetworkStatus, error)

GetNetworkPolicy returns reference-only desired/report/compliance state in the authorized scope. Usage: status, err := sdk.GetNetworkPolicy(ctx, scope, deviceID).

Policy

go/policies.go:12

type Policy = ports.Policy

LockTaskPolicy

go/policies.go:13

type LockTaskPolicy = ports.LockTaskPolicy

PermissionRule

go/policies.go:14

type PermissionRule = ports.PermissionRule

RestrictionRule

go/policies.go:15

type RestrictionRule = ports.RestrictionRule

DesiredPolicy

go/policies.go:16

type DesiredPolicy = ports.DesiredPolicy

PolicyStatus

go/policies.go:17

type PolicyStatus = ports.PolicyStatus

ManagedConfiguration

go/policies.go:18

type ManagedConfiguration = ports.ManagedConfiguration

ConfigurationBundle

go/policies.go:19

type ConfigurationBundle = ports.ConfigurationBundle

ConfigurationEntry

go/policies.go:20

type ConfigurationEntry = ports.ConfigurationEntry

ConfigurationValue

go/policies.go:21

type ConfigurationValue = ports.ConfigurationValue

*SDK.SetPolicy

go/policies.go:27

// SetPolicy replaces this device's policy. Required packages must already have
// scoped APK assignments; callers authorize scope/device before calling the SDK.
// An empty document releases only settings captured by Kylok's policy journal.
// Usage: desired, err := sdk.SetPolicy(ctx, scope, deviceID, requestKey, policy).
func (s *SDK) SetPolicy(ctx context.Context, scope, device, key string, p Policy) (DesiredPolicy, error)

SetPolicy replaces this device's policy. Required packages must already have scoped APK assignments; callers authorize scope/device before calling the SDK. An empty document releases only settings captured by Kylok's policy journal. Usage: desired, err := sdk.SetPolicy(ctx, scope, deviceID, requestKey, policy).

*SDK.GetPolicy

go/policies.go:47

// GetPolicy reads scoped desired/reported policy and per-rule compliance without treating assignment as enforcement.
// Usage: status, err := sdk.GetPolicy(ctx, scope, deviceID).
func (s *SDK) GetPolicy(ctx context.Context, scope, device string) (PolicyStatus, error)

GetPolicy reads scoped desired/reported policy and per-rule compliance without treating assignment as enforcement. Usage: status, err := sdk.GetPolicy(ctx, scope, deviceID).

ChangeRetention

go/ports/changes.go:11

const ChangeRetention = 10000

Changes are a bounded projection recovery log, never a permanent audit trail.

SnapshotLifetime

go/ports/changes.go:14

const SnapshotLifetime = 15 * time.Minute

SnapshotLifetime bounds retained consistent snapshots; hosts restart expired scans.

SnapshotLimit

go/ports/changes.go:17

const SnapshotLimit = 4

SnapshotLimit bounds simultaneous scans per scope, with oldest scans evicted explicitly.

ErrCursorExpired

go/ports/changes.go:19

var ErrCursorExpired = errors.New("cursor expired: resnapshot required")

Change

go/ports/changes.go:24

type Change struct {
    Sequence    uint64  `json:"sequence"`
    Kind        string  `json:"kind"`
    ResourceID  string  `json:"resource_id"`
}

Change invalidates one scoped device aggregate or catalog entry. It carries no payload/secrets. Device changes include desired state, reports, operations, inventory and revocation. Application removals are tombstones; other changes require authoritative scoped reads.

ChangesPage

go/ports/changes.go:31

type ChangesPage struct {
    Items   []Change
    Next    uint64
    Head    uint64
}

ChangesPage continues through a bounded scope log; Next always identifies the last delivered position.

DeviceState

go/ports/changes.go:38

type DeviceState struct {
    Network     NetworkStatus       `json:"network"`
    Device      Device          `json:"device"`
    Desired     []DesiredApplication    `json:"desired"`
    Operations  []Operation     `json:"operations"`
    Commands    []Command       `json:"commands"`
    Policy      PolicyStatus        `json:"policy"`
}

DeviceState is a consistent scoped aggregate for host projection, not an agent transport message.

ProjectionItem

go/ports/changes.go:48

type ProjectionItem struct {
    Device      *DeviceState        `json:"device,omitempty"`
    Application *Artifact       `json:"application,omitempty"`
    Group       *Group          `json:"group,omitempty"`
    Fleet       *FleetAssignment    `json:"fleet,omitempty"`
}

ProjectionItem is one immutable snapshot record. Exactly one resource pointer is set.

ProjectionPage

go/ports/changes.go:56

type ProjectionPage struct {
    Items       []ProjectionItem
    SnapshotID  string
    After       int
    More        bool
    Watermark   uint64
    ExpiresAt   time.Time
}

ProjectionPage carries a snapshot continuation and the change watermark for after the final page.

ChangeStore

go/ports/changes.go:66

type ChangeStore interface {
    // ListChanges reads only the explicit scope; stale cursors fail rather than silently skipping changes.
    // Usage: page, err := store.ListChanges(ctx, scope, lastSequence, 100).
    ListChanges(context.Context, string, uint64, int) (ChangesPage, error)
    // GetDeviceState atomically reads desired/observed state and complete operation history for one scoped device.
    // Usage: state, err := store.GetDeviceState(ctx, scope, deviceID).
    GetDeviceState(context.Context, string, string) (DeviceState, error)
    // ReadProjection starts a new consistent snapshot when snapshotID is empty; otherwise it reads saved immutable records.
    // Continuations require the same authorized scope, remain valid across process restart, and expire after SnapshotLifetime.
    // Usage: page, err := store.ReadProjection(ctx, scope, "", 0, 100, now).
    ReadProjection(context.Context, string, string, int, int, time.Time) (ProjectionPage, error)
}

ChangeStore is embedded in StateStore: state and invalidation records commit or roll back together.

ChangeStore.ListChanges

go/ports/changes.go:69

ListChanges(context.Context, string, uint64, int) (ChangesPage, error)

ListChanges reads only the explicit scope; stale cursors fail rather than silently skipping changes. Usage: page, err := store.ListChanges(ctx, scope, lastSequence, 100).

ChangeStore.GetDeviceState

go/ports/changes.go:72

GetDeviceState(context.Context, string, string) (DeviceState, error)

GetDeviceState atomically reads desired/observed state and complete operation history for one scoped device. Usage: state, err := store.GetDeviceState(ctx, scope, deviceID).

ChangeStore.ReadProjection

go/ports/changes.go:76

ReadProjection(context.Context, string, string, int, int, time.Time) (ProjectionPage, error)

ReadProjection starts a new consistent snapshot when snapshotID is empty; otherwise it reads saved immutable records. Continuations require the same authorized scope, remain valid across process restart, and expire after SnapshotLifetime. Usage: page, err := store.ReadProjection(ctx, scope, "", 0, 100, now).

Command

go/ports/commands.go:12

type Command struct {
    ID      string          `json:"id"`
    DeviceID    string          `json:"device_id"`
    Kind        string          `json:"kind"`
    State       string          `json:"state"`
    DispatchToken   string          `json:"dispatch_token,omitempty"`
    Deadline    time.Time       `json:"deadline"`
    ErrorCode   string          `json:"error_code,omitempty"`
    Observation *CommandObservation `json:"observation,omitempty"`
}

Command is a one-shot Android action. DispatchToken binds reports and never changes on retry. DISPATCHED means delivery was committed; UNCERTAIN never authorizes automatic replay. A successful reboot requires a boot-count increase; lock success requires secure, locked readback.

CommandObservation

go/ports/commands.go:24

type CommandObservation struct {
    BootBefore  int64   `json:"boot_before"`
    BootAfter   int64   `json:"boot_after"`
    Secure      bool    `json:"secure"`
    Locked      bool    `json:"locked"`
}

CommandObservation carries platform readback; transport reconnection and setter return are not observations.

CommandAssignment

go/ports/commands.go:32

type CommandAssignment struct {
    ScopeID, DeviceID, Kind, IdempotencyKey, ID string
    Now, Deadline                   time.Time
}

CommandAssignment binds the device/kind to a stable host request key before any dispatch.

CommandReport

go/ports/commands.go:39

type CommandReport struct {
    CommandID, DispatchToken, State, ErrorCode  string
    Observation                 *CommandObservation
}

CommandReport is a durable terminal result bound to the original command dispatch token. Exact repeats are accepted; changed reports for the same command conflict.

CommandStore

go/ports/commands.go:45

type CommandStore interface {
    // SubmitCommand binds a capability-gated reboot/lock request, with at most sixteen active commands per device.
    // Usage: command, err := store.SubmitCommand(ctx, assignment).
    SubmitCommand(context.Context, CommandAssignment) (Command, error)
    // GetCommand reads a scoped result and expires queued/dispatched work as FAILED/UNCERTAIN respectively.
    // Usage: command, err := store.GetCommand(ctx, scope, deviceID, commandID, now).
    GetCommand(context.Context, string, string, string, time.Time) (Command, error)
    // ListCommands pages one device's command history, expiring overdue work before the read.
    // Usage: commands, err := store.ListCommands(ctx, scope, deviceID, afterID, 20, now).
    ListCommands(context.Context, string, string, string, int, time.Time) ([]Command, error)
    // CancelCommand cancels only undispatched work; dispatched work becomes UNCERTAIN because it may have executed.
    // Usage: command, err := store.CancelCommand(ctx, scope, deviceID, commandID, now).
    CancelCommand(context.Context, string, string, string, time.Time) (Command, error)
}

CommandStore shares authentication, serialization and transactional changes with the agent state store.

CommandStore.SubmitCommand

go/ports/commands.go:48

SubmitCommand(context.Context, CommandAssignment) (Command, error)

SubmitCommand binds a capability-gated reboot/lock request, with at most sixteen active commands per device. Usage: command, err := store.SubmitCommand(ctx, assignment).

CommandStore.GetCommand

go/ports/commands.go:51

GetCommand(context.Context, string, string, string, time.Time) (Command, error)

GetCommand reads a scoped result and expires queued/dispatched work as FAILED/UNCERTAIN respectively. Usage: command, err := store.GetCommand(ctx, scope, deviceID, commandID, now).

CommandStore.ListCommands

go/ports/commands.go:54

ListCommands(context.Context, string, string, string, int, time.Time) ([]Command, error)

ListCommands pages one device's command history, expiring overdue work before the read. Usage: commands, err := store.ListCommands(ctx, scope, deviceID, afterID, 20, now).

CommandStore.CancelCommand

go/ports/commands.go:57

CancelCommand(context.Context, string, string, string, time.Time) (Command, error)

CancelCommand cancels only undispatched work; dispatched work becomes UNCERTAIN because it may have executed. Usage: command, err := store.CancelCommand(ctx, scope, deviceID, commandID, now).

ManagedConfiguration

go/ports/configuration.go:19

type ManagedConfiguration struct {
    PackageName string          `json:"package_name"`
    Values      ConfigurationBundle `json:"values"`
}

ManagedConfiguration owns the complete restrictions bundle for a required managed app. Absence from a replacement policy releases only the bundle journaled by Kylok.

ConfigurationBundle

go/ports/configuration.go:25

type ConfigurationBundle struct {
    Entries []ConfigurationEntry `json:"entries"`
}

ConfigurationBundle is a bounded typed Android Bundle. Normalization sorts keys; array order remains significant.

ConfigurationEntry

go/ports/configuration.go:30

type ConfigurationEntry struct {
    Key string          `json:"key"`
    Value   ConfigurationValue  `json:"value"`
}

ConfigurationEntry assigns one unique application-defined key to exactly one typed value.

ConfigurationValue

go/ports/configuration.go:37

type ConfigurationValue struct {
    Boolean *bool           `json:"boolean,omitempty"`
    Integer *int32          `json:"integer,omitempty"`
    String  *string         `json:"string,omitempty"`
    Strings *[]string       `json:"strings,omitempty"`
    Bundle  *ConfigurationBundle    `json:"bundle,omitempty"`
    Bundles *[]ConfigurationBundle  `json:"bundles,omitempty"`
}

ConfigurationValue selects exactly one nonnil pointer. Empty strings/arrays/bundles are supported values. Boolean/int/string pointers preserve explicit zero values and prevent type inference from generic JSON.

MaximumPolicyResults

go/ports/configuration.go:47

const MaximumPolicyResults = 201

MaximumPolicyResults covers 64 required apps, permissions and configurations, four restrictions, three scalars, kiosk and cleanup.

ConfigurationMessage

go/ports/configuration.go:166

// ConfigurationMessage preserves explicit scalar values and typed arrays at the wire boundary.
// The input must be normalized with NormalizePolicy before hashing or transmission.
// Usage: wire := ports.ConfigurationMessage(normalized.ManagedConfigurations[0].Values).
func ConfigurationMessage(bundle ConfigurationBundle) *v1.ConfigurationBundle

ConfigurationMessage preserves explicit scalar values and typed arrays at the wire boundary. The input must be normalized with NormalizePolicy before hashing or transmission. Usage: wire := ports.ConfigurationMessage(normalized.ManagedConfigurations[0].Values).

ConfigurationDigest

go/ports/configuration.go:196

// ConfigurationDigest reports only a digest of normalized typed content, never configuration values.
// A matching DPC readback is separate from acknowledgement that an application applied the configuration.
// Usage: expected := ports.ConfigurationDigest(normalized.ManagedConfigurations[0].Values).
func ConfigurationDigest(bundle ConfigurationBundle) string

ConfigurationDigest reports only a digest of normalized typed content, never configuration values. A matching DPC readback is separate from acknowledgement that an application applied the configuration. Usage: expected := ports.ConfigurationDigest(normalized.ManagedConfigurations[0].Values).

MaximumFleetDevices

go/ports/fleet.go:10

const MaximumFleetDevices = 100

MaximumFleetDevices bounds membership snapshots and per-request partial results.

Group

go/ports/fleet.go:14

type Group struct {
    ScopeID     string      `json:"scope_id"`
    ID      string      `json:"id"`
    Revision    uint64      `json:"revision"`
    DeviceIDs   []string    `json:"device_ids"`
}

Group is a scoped, opaque membership set. Revision is a compare-and-swap token. Groups select targets at submission; membership edits do not alter an existing fleet assignment.

FleetRequest

go/ports/fleet.go:23

type FleetRequest struct {
    ScopeID     string      `json:"scope_id"`
    ID      string      `json:"id"`
    GroupID     string      `json:"group_id,omitempty"`
    DeviceIDs   []string    `json:"device_ids,omitempty"`
    ArtifactSHA256  string      `json:"artifact_sha256"`
    NotBefore   time.Time   `json:"not_before"`
    Deadline    time.Time   `json:"deadline"`
}

FleetRequest binds an immutable absolute deployment window and exactly one target selector. ID is a scope-local idempotency key. DeviceIDs are sorted and unique; GroupID freezes its members.

FleetItem

go/ports/fleet.go:36

type FleetItem struct {
    DeviceID    string  `json:"device_id"`
    State       string  `json:"state"`
    OperationID string  `json:"operation_id,omitempty"`
    ErrorCode   string  `json:"error_code,omitempty"`
}

FleetItem records fan-out progress, not device compliance. ASSIGNED has a durable OperationID; FAILED is a permanent per-device rejection; PENDING can be resumed; CANCELLED was not submitted. Read the device operation to observe installation outcome after ASSIGNED.

FleetAssignment

go/ports/fleet.go:45

type FleetAssignment struct {
    Request     FleetRequest    `json:"request"`
    GroupRevision   uint64      `json:"group_revision,omitempty"`
    Items       []FleetItem `json:"items"`
    Complete    bool        `json:"complete"`
    Cancelled   bool        `json:"cancelled"`
}

FleetAssignment persists the frozen target list and bounded per-device results. Complete means fan-out has no pending items; it does not mean APKs were installed.

FleetStore

go/ports/fleet.go:55

type FleetStore interface {
    // ReplaceGroup atomically replaces membership if expectedRevision matches (zero creates).
    // An identical retry at expectedRevision+1 returns the committed group; foreign devices are rejected.
    // Usage: group, err := store.ReplaceGroup(ctx, Group{ScopeID: scope, ID: id, DeviceIDs: ids}, expectedRevision).
    ReplaceGroup(context.Context, Group, uint64) (Group, error)
    // GetGroup returns detached membership in exactly one authorized scope.
    // Usage: group, err := store.GetGroup(ctx, scope, groupID).
    GetGroup(context.Context, string, string) (Group, error)
    // ListGroups returns live ascending-ID pages, including empty groups.
    // Usage: groups, err := store.ListGroups(ctx, scope, afterID, 20).
    ListGroups(context.Context, string, string, int) ([]Group, error)
    // CreateFleetAssignment atomically freezes targets and binds the request; no device effect occurs here.
    // Usage: batch, err := store.CreateFleetAssignment(ctx, request, now).
    CreateFleetAssignment(context.Context, FleetRequest, time.Time) (FleetAssignment, error)
    // GetFleetAssignment returns the exact frozen request and fan-out checkpoint.
    // Usage: batch, err := store.GetFleetAssignment(ctx, scope, batchID).
    GetFleetAssignment(context.Context, string, string) (FleetAssignment, error)
    // ListFleetAssignments pages durable batches so a restarted host can resume incomplete fan-out.
    // Usage: batches, err := store.ListFleetAssignments(ctx, scope, afterID, 20).
    ListFleetAssignments(context.Context, string, string, int) ([]FleetAssignment, error)
    // AdvanceFleetAssignment atomically submits at most limit pending devices, with per-device stable keys.
    // Permanent domain rejections become item failures; storage/context errors roll back this advance.
    // Usage: batch, err := store.AdvanceFleetAssignment(ctx, scope, batchID, now, 20).
    AdvanceFleetAssignment(context.Context, string, string, time.Time, int) (FleetAssignment, error)
    // CancelFleetAssignment stops pending fan-out and cancels submitted active work, preserving completed effects.
    // Usage: batch, err := store.CancelFleetAssignment(ctx, scope, batchID, now).
    CancelFleetAssignment(context.Context, string, string, time.Time) (FleetAssignment, error)
    // CancelOperation stops future dispatch/download; an already delivered platform effect may still finish.
    // Desired assignment stays recorded; no implicit rollback/uninstall or future drift retry is created.
    // Usage: operation, err := store.CancelOperation(ctx, scope, deviceID, operationID, now).
    CancelOperation(context.Context, string, string, string, time.Time) (Operation, error)
}

FleetStore extends the same serialized state boundary used by assignments and sync. Every mutation records scoped change-feed invalidations in its transaction.

FleetStore.ReplaceGroup

go/ports/fleet.go:59

ReplaceGroup(context.Context, Group, uint64) (Group, error)

ReplaceGroup atomically replaces membership if expectedRevision matches (zero creates). An identical retry at expectedRevision+1 returns the committed group; foreign devices are rejected. Usage: group, err := store.ReplaceGroup(ctx, Group{ScopeID: scope, ID: id, DeviceIDs: ids}, expectedRevision).

FleetStore.GetGroup

go/ports/fleet.go:62

GetGroup(context.Context, string, string) (Group, error)

GetGroup returns detached membership in exactly one authorized scope. Usage: group, err := store.GetGroup(ctx, scope, groupID).

FleetStore.ListGroups

go/ports/fleet.go:65

ListGroups(context.Context, string, string, int) ([]Group, error)

ListGroups returns live ascending-ID pages, including empty groups. Usage: groups, err := store.ListGroups(ctx, scope, afterID, 20).

FleetStore.CreateFleetAssignment

go/ports/fleet.go:68

CreateFleetAssignment(context.Context, FleetRequest, time.Time) (FleetAssignment, error)

CreateFleetAssignment atomically freezes targets and binds the request; no device effect occurs here. Usage: batch, err := store.CreateFleetAssignment(ctx, request, now).

FleetStore.GetFleetAssignment

go/ports/fleet.go:71

GetFleetAssignment(context.Context, string, string) (FleetAssignment, error)

GetFleetAssignment returns the exact frozen request and fan-out checkpoint. Usage: batch, err := store.GetFleetAssignment(ctx, scope, batchID).

FleetStore.ListFleetAssignments

go/ports/fleet.go:74

ListFleetAssignments(context.Context, string, string, int) ([]FleetAssignment, error)

ListFleetAssignments pages durable batches so a restarted host can resume incomplete fan-out. Usage: batches, err := store.ListFleetAssignments(ctx, scope, afterID, 20).

FleetStore.AdvanceFleetAssignment

go/ports/fleet.go:78

AdvanceFleetAssignment(context.Context, string, string, time.Time, int) (FleetAssignment, error)

AdvanceFleetAssignment atomically submits at most limit pending devices, with per-device stable keys. Permanent domain rejections become item failures; storage/context errors roll back this advance. Usage: batch, err := store.AdvanceFleetAssignment(ctx, scope, batchID, now, 20).

FleetStore.CancelFleetAssignment

go/ports/fleet.go:81

CancelFleetAssignment(context.Context, string, string, time.Time) (FleetAssignment, error)

CancelFleetAssignment stops pending fan-out and cancels submitted active work, preserving completed effects. Usage: batch, err := store.CancelFleetAssignment(ctx, scope, batchID, now).

FleetStore.CancelOperation

go/ports/fleet.go:85

CancelOperation(context.Context, string, string, string, time.Time) (Operation, error)

CancelOperation stops future dispatch/download; an already delivered platform effect may still finish. Desired assignment stays recorded; no implicit rollback/uninstall or future drift retry is created. Usage: operation, err := store.CancelOperation(ctx, scope, deviceID, operationID, now).

WifiProfile

go/ports/network.go:17

type WifiProfile struct {
    ID      string  `json:"id"`
    SSID        string  `json:"ssid"`
    Security    string  `json:"security"`
    SecretRef   string  `json:"secret_ref,omitempty"`
    Hidden      bool    `json:"hidden"`
}

WifiProfile describes a managed saved network. Secrets are immutable host references, never passwords. Security is OPEN, WPA2_PSK or WPA3_SAE. SSID is literal UTF-8, limited to 32 bytes.

CACertificate

go/ports/network.go:26

type CACertificate struct {
    ID  string  `json:"id"`
    DER []byte  `json:"der"`
}

CACertificate is one DER-encoded CA, without a private key. ID is an opaque ownership label.

NetworkPolicy

go/ports/network.go:34

type NetworkPolicy struct {
    PrimaryID   string      `json:"primary_id"`
    Profiles    []WifiProfile   `json:"profiles"`
    Certificates    []CACertificate `json:"certificates"`
}

NetworkPolicy is a full replacement of at most eight Wi-Fi profiles and eight private CAs. PrimaryID chooses the network requiring authenticated management connectivity. An empty document releases ownership. The Android agent preserves an independent saved recovery route before applying or releasing managed settings.

DesiredNetworkPolicy

go/ports/network.go:41

type DesiredNetworkPolicy struct {
    Revision    uint64      `json:"revision"`
    Policy      NetworkPolicy   `json:"policy"`
}

DesiredNetworkPolicy binds the normalized document to a shared device desired revision.

NetworkReport

go/ports/network.go:48

type NetworkReport struct {
    Revision        uint64  `json:"revision"`
    State           string  `json:"state"`
    Reason          string  `json:"reason"`
    ActiveProfileID     string  `json:"active_profile_id"`
    ConnectivityVerified    bool    `json:"connectivity_verified"`
    CleanupComplete     bool    `json:"cleanup_complete"`
}

NetworkReport distinguishes readback and authenticated route verification from setters and Wi-Fi association. APPLIED requires primary/recovery connectivity and completion of only the managed-resource cleanup.

NetworkStatus

go/ports/network.go:58

type NetworkStatus struct {
    Desired     *DesiredNetworkPolicy   `json:"desired,omitempty"`
    Reported    *NetworkReport      `json:"reported,omitempty"`
    State       string          `json:"state"`
    Reason      string          `json:"reason"`
}

NetworkStatus contains no delivered passwords. Reported state remains separate from current desired compliance.

NetworkAssignment

go/ports/network.go:66

type NetworkAssignment struct {
    ScopeID, DeviceID, IdempotencyKey   string
    Policy                  NetworkPolicy
}

NetworkAssignment atomically binds a complete normalized replacement to a scoped device/request key.

NetworkSecretProvider

go/ports/network.go:75

type NetworkSecretProvider interface {
    // ReadNetworkSecret returns the passphrase bound to an immutable scoped reference; nil/error fails closed.
    // Usage: secret, err := vault.ReadNetworkSecret(ctx, scope, "wifi-key-version-2").
    ReadNetworkSecret(context.Context, string, string) ([]byte, error)
}

NetworkSecretProvider resolves immutable versioned references only within an explicitly authorized scope. References must retain identical bytes across retries/restarts. Rotate with a new reference and desired revision. The host owns persistence, encryption, access control and lifetime; failures never permit empty-secret fallback. Returned bytes belong to the caller. Do not log secret values or place them in public snapshots/events.

NetworkSecretProvider.ReadNetworkSecret

go/ports/network.go:78

ReadNetworkSecret(context.Context, string, string) ([]byte, error)

ReadNetworkSecret returns the passphrase bound to an immutable scoped reference; nil/error fails closed. Usage: secret, err := vault.ReadNetworkSecret(ctx, scope, "wifi-key-version-2").

NetworkStore

go/ports/network.go:82

type NetworkStore interface {
    // GetNetworkRequest reads the original scoped replacement receipt without resolving secret references.
    // Usage: desired, err := store.GetNetworkRequest(ctx, scope, deviceID, requestKey).
    GetNetworkRequest(context.Context, string, string, string) (DesiredNetworkPolicy, error)
    // SetNetworkPolicy binds a normalized document/key, advances desired revision once and records a device change.
    // Usage: desired, err := store.SetNetworkPolicy(ctx, assignment).
    SetNetworkPolicy(context.Context, NetworkAssignment) (DesiredNetworkPolicy, error)
    // GetNetworkPolicy reads consistent desired/reported/compliance state in exactly one authorized scope.
    // Usage: status, err := store.GetNetworkPolicy(ctx, scope, deviceID).
    GetNetworkPolicy(context.Context, string, string) (NetworkStatus, error)
}

NetworkStore shares policy/secret-reference state and report invalidations with the serialized device store.

NetworkStore.GetNetworkRequest

go/ports/network.go:85

GetNetworkRequest(context.Context, string, string, string) (DesiredNetworkPolicy, error)

GetNetworkRequest reads the original scoped replacement receipt without resolving secret references. Usage: desired, err := store.GetNetworkRequest(ctx, scope, deviceID, requestKey).

NetworkStore.SetNetworkPolicy

go/ports/network.go:88

SetNetworkPolicy(context.Context, NetworkAssignment) (DesiredNetworkPolicy, error)

SetNetworkPolicy binds a normalized document/key, advances desired revision once and records a device change. Usage: desired, err := store.SetNetworkPolicy(ctx, assignment).

NetworkStore.GetNetworkPolicy

go/ports/network.go:91

GetNetworkPolicy(context.Context, string, string) (NetworkStatus, error)

GetNetworkPolicy reads consistent desired/reported/compliance state in exactly one authorized scope. Usage: status, err := store.GetNetworkPolicy(ctx, scope, deviceID).

NormalizeNetworkPolicy

go/ports/network.go:102

// NormalizeNetworkPolicy detaches, validates and sorts a bounded replacement before idempotency comparison.
// Certificate validity is checked again at delivery/application time; certificates must be complete CA DER objects.
// Usage: policy, err := ports.NormalizeNetworkPolicy(input).
func NormalizeNetworkPolicy(input NetworkPolicy) (NetworkPolicy, error)

NormalizeNetworkPolicy detaches, validates and sorts a bounded replacement before idempotency comparison. Certificate validity is checked again at delivery/application time; certificates must be complete CA DER objects. Usage: policy, err := ports.NormalizeNetworkPolicy(input).

Policy

go/ports/policy.go:15

type Policy struct {
    ManagedConfigurations   []ManagedConfiguration  `json:"managed_configurations,omitempty"`
    RequiredPackages    []string        `json:"required_packages,omitempty"`
    LockTask        *LockTaskPolicy     `json:"lock_task,omitempty"`
    CameraDisabled      *bool           `json:"camera_disabled,omitempty"`
    ScreenCaptureDisabled   *bool           `json:"screen_capture_disabled,omitempty"`
    Restrictions        []RestrictionRule   `json:"restrictions,omitempty"`
    Permissions     []PermissionRule    `json:"permissions,omitempty"`
    MaximumTimeToLockMillis *int64          `json:"maximum_time_to_lock_millis,omitempty"`
}

LockTaskPolicy

go/ports/policy.go:25

type LockTaskPolicy struct {
    Packages    []string    `json:"packages"`
    KioskPackage    string      `json:"kiosk_package"`
}

RestrictionRule

go/ports/policy.go:29

type RestrictionRule struct {
    Name    string  `json:"name"`
    Enabled bool    `json:"enabled"`
}

PermissionRule

go/ports/policy.go:33

type PermissionRule struct {
    PackageName string  `json:"package_name"`
    Permission  string  `json:"permission"`
    State       string  `json:"state"`
}

DesiredPolicy

go/ports/policy.go:38

type DesiredPolicy struct {
    Revision    uint64  `json:"revision"`
    Policy      Policy  `json:"policy"`
}

PolicyAssignment

go/ports/policy.go:42

type PolicyAssignment struct {
    ScopeID, DeviceID, IdempotencyKey   string
    Policy                  Policy
}

PolicyResult

go/ports/policy.go:46

type PolicyResult struct {
    RuleID      string  `json:"rule_id"`
    State       string  `json:"state"`
    Reason      string  `json:"reason"`
    ObservedValue   string  `json:"observed_value"`
}

PolicyReport

go/ports/policy.go:52

type PolicyReport struct {
    Revision        uint64      `json:"revision"`
    SnapshotRevision    uint64      `json:"snapshot_revision"`
    Results         []PolicyResult  `json:"results"`
}

PolicyStatus

go/ports/policy.go:57

type PolicyStatus struct {
    Desired     *DesiredPolicy  `json:"desired,omitempty"`
    Reported    *PolicyReport   `json:"reported,omitempty"`
    Compliance  []PolicyResult  `json:"compliance"`
}

NormalizePolicy

go/ports/policy.go:69

// NormalizePolicy validates and copies the document, sorting unordered sets for
// stable idempotency. A setting's absence differs from an explicit false/zero.
// Usage: normalized, err := ports.NormalizePolicy(policy).
func NormalizePolicy(input Policy) (Policy, error)

NormalizePolicy validates and copies the document, sorting unordered sets for stable idempotency. A setting's absence differs from an explicit false/zero. Usage: normalized, err := ports.NormalizePolicy(policy).

PolicyExpectations

go/ports/policy.go:144

// PolicyExpectations defines canonical values shared with the Android observer.
// Required apps bind package/version/signers, so changing an APK invalidates an
// earlier policy observation even if the policy document itself is unchanged.
// Usage: values := ports.PolicyExpectations(policy, desiredApps).
func PolicyExpectations(p Policy, apps []DesiredApplication) map[string]string

PolicyExpectations defines canonical values shared with the Android observer. Required apps bind package/version/signers, so changing an APK invalidates an earlier policy observation even if the policy document itself is unchanged. Usage: values := ports.PolicyExpectations(policy, desiredApps).

PolicyCapability

go/ports/policy.go:192

// PolicyCapability identifies the agent capability required to implement one canonical rule ID.
// Usage: capability := ports.PolicyCapability("camera").
func PolicyCapability(key string) string

PolicyCapability identifies the agent capability required to implement one canonical rule ID. Usage: capability := ports.PolicyCapability("camera").

Changes

go/ports/portstest/changes.go:17

// Changes verifies transactional invalidations, scoped replay, immutable snapshots and explicit expiry/eviction.
// Usage: portstest.Changes(t, factory); run unchanged for both durable SQL adapters.
func Changes(t *testing.T, factory func(*testing.T) ports.StateStore)

Changes verifies transactional invalidations, scoped replay, immutable snapshots and explicit expiry/eviction. Usage: portstest.Changes(t, factory); run unchanged for both durable SQL adapters.

Commands

go/ports/portstest/commands.go:15

// Commands verifies capability gates, stable delivery, report binding, honest uncertainty and scope isolation.
// Usage: portstest.Commands(t, factory).
func Commands(t *testing.T, factory func(*testing.T) ports.StateStore)

Commands verifies capability gates, stable delivery, report binding, honest uncertainty and scope isolation. Usage: portstest.Commands(t, factory).

Fleet

go/ports/portstest/fleet.go:39

// Fleet verifies frozen membership, bounded/restartable fan-out, windows, cancellation, isolation and replay on every provider.
// Usage: portstest.Fleet(t, factory).
func Fleet(t *testing.T, factory func(*testing.T) ports.StateStore)

Fleet verifies frozen membership, bounded/restartable fan-out, windows, cancellation, isolation and replay on every provider. Usage: portstest.Fleet(t, factory).

Management

go/ports/portstest/management.go:16

// Management verifies correlation binding, scoped point/filter reads, expiry and cancellation.
// Usage: portstest.Management(t, factory); run this unchanged for every state adapter.
func Management(t *testing.T, factory func(*testing.T) ports.StateStore)

Management verifies correlation binding, scoped point/filter reads, expiry and cancellation. Usage: portstest.Management(t, factory); run this unchanged for every state adapter.

Network

go/ports/portstest/network.go:15

// Network verifies scoped reference-only intent, idempotency, observed connectivity and atomic rollback with command effects.
// Usage: portstest.Network(t, factory).
func Network(t *testing.T, factory func(*testing.T) ports.StateStore)

Network verifies scoped reference-only intent, idempotency, observed connectivity and atomic rollback with command effects. Usage: portstest.Network(t, factory).

Operations

go/ports/portstest/operations.go:16

// Operations verifies storage-level atomic reports, replay, assignments and retention.
// Usage: portstest.Operations(t, factory).
func Operations(t *testing.T, factory func(*testing.T) ports.StateStore)

Operations verifies storage-level atomic reports, replay, assignments and retention. Usage: portstest.Operations(t, factory).

Policies

go/ports/portstest/policies.go:17

// Policies checks scope, idempotent replacement, observed compliance, atomic
// rollback and revocation for custom providers as well as the default adapter.
// Usage: portstest.Policies(t, factory).
func Policies(t *testing.T, factory func(*testing.T) ports.StateStore)

Policies checks scope, idempotent replacement, observed compliance, atomic rollback and revocation for custom providers as well as the default adapter. Usage: portstest.Policies(t, factory).

ManagedConfigurations

go/ports/portstest/policies.go:94

// ManagedConfigurations verifies typed config idempotency and honest current-snapshot readback on any adapter.
// Usage: portstest.ManagedConfigurations(t, factory).
func ManagedConfigurations(t *testing.T, factory func(*testing.T) ports.StateStore)

ManagedConfigurations verifies typed config idempotency and honest current-snapshot readback on any adapter. Usage: portstest.ManagedConfigurations(t, factory).

State

go/ports/portstest/state.go:20

// State runs against a fresh durable store. Callers should separately prove
// process-restart persistence, resource ownership and backend-specific failures.
// Usage: portstest.State(t, factory).
func State(t *testing.T, factory func(*testing.T) ports.StateStore)

State runs against a fresh durable store. Callers should separately prove process-restart persistence, resource ownership and backend-specific failures. Usage: portstest.State(t, factory).

ErrInvalidArgument

go/ports/state.go:13

var ErrInvalidArgument = errors.New("invalid argument")

ErrNotFound

go/ports/state.go:14

var ErrNotFound = errors.New("not found")

ErrExpired

go/ports/state.go:15

var ErrExpired = errors.New("enrollment expired")

ErrConsumed

go/ports/state.go:16

var ErrConsumed = errors.New("enrollment consumed by another attempt")

ErrRecoveryExpired

go/ports/state.go:17

var ErrRecoveryExpired = errors.New("enrollment recovery expired")

ErrRevoked

go/ports/state.go:18

var ErrRevoked = errors.New("device revoked")

ErrUnauthorized

go/ports/state.go:19

var ErrUnauthorized = errors.New("invalid device credential")

ErrConflict

go/ports/state.go:20

var ErrConflict = errors.New("conflicting idempotency payload")

ErrUnsupported

go/ports/state.go:21

var ErrUnsupported = errors.New("device capability unsupported")

ErrStale

go/ports/state.go:22

var ErrStale = errors.New("stale sync sequence")

ErrReferenced

go/ports/state.go:23

var ErrReferenced = errors.New("artifact is referenced by desired state or pending work")

Inventory

go/ports/state.go:26

type Inventory struct {
    APILevel        uint32          `json:"api_level"`
    Model           string          `json:"model"`
    BuildFingerprint    string          `json:"build_fingerprint"`
    AgentVersion        string          `json:"agent_version"`
    DeviceOwner     bool            `json:"device_owner"`
    Capabilities        []string        `json:"capabilities"`
    Applications        []InstalledApplication  `json:"applications"`
    SupportedABIs       []string        `json:"supported_abis"`
}

InstalledApplication

go/ports/state.go:36

type InstalledApplication struct {
    PackageName     string      `json:"package_name"`
    VersionCode     int64       `json:"version_code"`
    SigningCertificates []string    `json:"signing_certificates"`
}

Device

go/ports/state.go:41

type Device struct {
    CorrelationID       string      `json:"correlation_id,omitempty"`
    ID          string      `json:"id"`
    ScopeID         string      `json:"scope_id"`
    State           string      `json:"state"`
    Inventory       Inventory   `json:"inventory"`
    CreatedAt       time.Time   `json:"created_at"`
    LastSeenAt      time.Time   `json:"last_seen_at"`
    DesiredRevision     uint64      `json:"desired_revision"`
    ReportedRevision    uint64      `json:"reported_revision"`
}

Enrollment

go/ports/state.go:52

type Enrollment struct {
    CorrelationID   string
    TokenHash   []byte
    ScopeID     string
    ExpiresAt   time.Time
    ArtifactSHA256  string
}

Attempt

go/ports/state.go:59

type Attempt struct {
    TokenHash   []byte
    ID      string
    KeyHash     []byte
    Device      Device
    CredentialHash  []byte
    // Encoded encrypted response; never contains a plaintext credential.
    Receipt     []byte
    Now     time.Time
    RecoverUntil    time.Time
}

DeviceQuery

go/ports/state.go:84

type DeviceQuery struct {
    ScopeID, After, State, CorrelationID    string
    Limit                   int
}

StateStore methods are safe for concurrent calls. Every operation respects context cancellation. Consume atomically validates expiry, consumes the token, inserts the device and persists its encrypted receipt. A matching ID AND key hash retrieves the original receipt until RecoverUntil, including after token expiry. Other attempts fail; revoked devices cannot recover. Revocation and Sync are serialized. Returned slices/values belong to the caller. Hosts close custom stores themselves. SetPolicy atomically validates scope/required assignments, binds the normalized document to the device/key, and advances the shared desired revision once. Sync binds policy observations to its replay body and the desired snapshot; stale observations cannot establish current compliance. GetPolicy reads a consistent scoped desired/reported/compliance view. See portstest.Policies. DeviceQuery is a live keyset read. Mutable filters are evaluated at read time; inserts behind After need a new scan. CorrelationID is an exact opaque match.

OperationQuery

go/ports/state.go:90

type OperationQuery struct {
    ScopeID, DeviceID, After, State string
    Limit               int
    Now             time.Time
}

OperationQuery filters a single authorized device's live operation history.

StateStore

go/ports/state.go:96

type StateStore interface {
    ChangeStore
    FleetStore
    CommandStore
    NetworkStore
    // Check verifies that the persistence backend is reachable without changing state.
    // Usage: err := store.Check(ctx).
    Check(context.Context) error
    // GetDevice returns one scoped identity, never its credential verifier.
    // Usage: device, err := store.GetDevice(ctx, scope, deviceID).
    GetDevice(context.Context, string, string) (Device, error)
    // QueryDevices reads an exact scoped live page; callers own returned values.
    // Usage: devices, err := store.QueryDevices(ctx, DeviceQuery{ScopeID: scope, Limit: 20}).
    QueryDevices(context.Context, DeviceQuery) ([]Device, error)
    // GetOperation expires overdue work and reads one operation belonging to the scoped device.
    // Usage: operation, err := store.GetOperation(ctx, scope, deviceID, operationID, now).
    GetOperation(context.Context, string, string, string, time.Time) (Operation, error)
    // QueryOperations expires overdue work and reads a scoped, state-filtered live page.
    // Usage: operations, err := store.QueryOperations(ctx, OperationQuery{ScopeID: scope, DeviceID: deviceID, Limit: 20, Now: now}).
    QueryOperations(context.Context, OperationQuery) ([]Operation, error)
    // Persist a verifier-only enrollment bound to scope, expiry and bootstrap bytes.
    // Usage: err := store.CreateEnrollment(ctx, enrollment).
    CreateEnrollment(context.Context, Enrollment) error
    // Read the original enrollment binding using its token verifier.
    // Usage: enrollment, err := store.Enrollment(ctx, tokenHash).
    Enrollment(context.Context, []byte) (Enrollment, error)
    // Atomically claim a token or recover the same encrypted receipt for its bound attempt and key.
    // Usage: receipt, err := store.Consume(ctx, attempt).
    Consume(context.Context, Attempt) ([]byte, error)
    // Authenticate one device credential and reject revoked identities.
    // Usage: device, err := store.Authenticate(ctx, deviceID, credentialHash).
    Authenticate(context.Context, string, []byte) (Device, error)
    // Atomically bind replay input, accept reports and persist the returned desired/observed snapshot.
    // Usage: snapshot, err := store.Sync(ctx, input).
    Sync(context.Context, SyncInput) (Snapshot, error)
    // Read one authorized scope's stable device cursor page.
    // Usage: devices, err := store.ListDevices(ctx, scope, "", 100).
    ListDevices(context.Context, string, string, int) ([]Device, error)
    // Serialize revocation with enrollment recovery and authenticated sync.
    // Usage: err := store.Revoke(ctx, scope, deviceID).
    Revoke(context.Context, string, string) error
    // Register immutable verified metadata for a scope/digest.
    // Usage: err := store.RegisterArtifact(ctx, artifact).
    RegisterArtifact(context.Context, Artifact) error
    // ListArtifacts returns scoped managed metadata in ascending digest order.
    // Usage: page, err := store.ListArtifacts(ctx, scope, lastDigest, 100).
    ListArtifacts(context.Context, string, string, int) ([]Artifact, error)
    // Read one scope/digest without crossing tenant boundaries.
    // Usage: artifact, err := store.Artifact(ctx, scope, digest).
    Artifact(context.Context, string, string) (Artifact, error)
    // Remove only unreferenced scoped metadata, retaining shared content safely.
    // Usage: err := store.RemoveArtifact(ctx, scope, digest).
    RemoveArtifact(context.Context, string, string) error
    // Atomically bind an install request key, desired revision and supersession of pending work.
    // Usage: operation, err := store.Assign(ctx, assignment).
    Assign(context.Context, Assignment) (Operation, error)
    // Expire overdue work and page scoped durable progress/results.
    // Usage: operations, err := store.ListOperations(ctx, scope, deviceID, "", 100, now).
    ListOperations(context.Context, string, string, string, int, time.Time) ([]Operation, error)
    // Verify device credential, scope, active operation/lease and deadline before returning metadata.
    // Usage: artifact, err := store.AuthorizeDownload(ctx, deviceID, credentialHash, operationID, digest, leaseID, now).
    AuthorizeDownload(context.Context, string, []byte, string, string, string, time.Time) (Artifact, error)
    // Atomically bind a normalized replacement and validate every required app assignment.
    // Usage: desired, err := store.SetPolicy(ctx, assignment).
    SetPolicy(context.Context, PolicyAssignment) (DesiredPolicy, error)
    // Return consistent scoped desired/reported/compliance state.
    // Usage: status, err := store.GetPolicy(ctx, scope, deviceID).
    GetPolicy(context.Context, string, string) (PolicyStatus, error)
}

StateStore.Check

go/ports/state.go:103

Check(context.Context) error

Check verifies that the persistence backend is reachable without changing state. Usage: err := store.Check(ctx).

StateStore.GetDevice

go/ports/state.go:106

GetDevice(context.Context, string, string) (Device, error)

GetDevice returns one scoped identity, never its credential verifier. Usage: device, err := store.GetDevice(ctx, scope, deviceID).

StateStore.QueryDevices

go/ports/state.go:109

QueryDevices(context.Context, DeviceQuery) ([]Device, error)

QueryDevices reads an exact scoped live page; callers own returned values. Usage: devices, err := store.QueryDevices(ctx, DeviceQuery{ScopeID: scope, Limit: 20}).

StateStore.GetOperation

go/ports/state.go:112

GetOperation(context.Context, string, string, string, time.Time) (Operation, error)

GetOperation expires overdue work and reads one operation belonging to the scoped device. Usage: operation, err := store.GetOperation(ctx, scope, deviceID, operationID, now).

StateStore.QueryOperations

go/ports/state.go:115

QueryOperations(context.Context, OperationQuery) ([]Operation, error)

QueryOperations expires overdue work and reads a scoped, state-filtered live page. Usage: operations, err := store.QueryOperations(ctx, OperationQuery{ScopeID: scope, DeviceID: deviceID, Limit: 20, Now: now}).

StateStore.CreateEnrollment

go/ports/state.go:118

CreateEnrollment(context.Context, Enrollment) error

Persist a verifier-only enrollment bound to scope, expiry and bootstrap bytes. Usage: err := store.CreateEnrollment(ctx, enrollment).

StateStore.Enrollment

go/ports/state.go:121

Enrollment(context.Context, []byte) (Enrollment, error)

Read the original enrollment binding using its token verifier. Usage: enrollment, err := store.Enrollment(ctx, tokenHash).

StateStore.Consume

go/ports/state.go:124

Consume(context.Context, Attempt) ([]byte, error)

Atomically claim a token or recover the same encrypted receipt for its bound attempt and key. Usage: receipt, err := store.Consume(ctx, attempt).

StateStore.Authenticate

go/ports/state.go:127

Authenticate(context.Context, string, []byte) (Device, error)

Authenticate one device credential and reject revoked identities. Usage: device, err := store.Authenticate(ctx, deviceID, credentialHash).

StateStore.Sync

go/ports/state.go:130

Sync(context.Context, SyncInput) (Snapshot, error)

Atomically bind replay input, accept reports and persist the returned desired/observed snapshot. Usage: snapshot, err := store.Sync(ctx, input).

StateStore.ListDevices

go/ports/state.go:133

ListDevices(context.Context, string, string, int) ([]Device, error)

Read one authorized scope's stable device cursor page. Usage: devices, err := store.ListDevices(ctx, scope, "", 100).

StateStore.Revoke

go/ports/state.go:136

Revoke(context.Context, string, string) error

Serialize revocation with enrollment recovery and authenticated sync. Usage: err := store.Revoke(ctx, scope, deviceID).

StateStore.RegisterArtifact

go/ports/state.go:139

RegisterArtifact(context.Context, Artifact) error

Register immutable verified metadata for a scope/digest. Usage: err := store.RegisterArtifact(ctx, artifact).

StateStore.ListArtifacts

go/ports/state.go:142

ListArtifacts(context.Context, string, string, int) ([]Artifact, error)

ListArtifacts returns scoped managed metadata in ascending digest order. Usage: page, err := store.ListArtifacts(ctx, scope, lastDigest, 100).

StateStore.Artifact

go/ports/state.go:145

Artifact(context.Context, string, string) (Artifact, error)

Read one scope/digest without crossing tenant boundaries. Usage: artifact, err := store.Artifact(ctx, scope, digest).

StateStore.RemoveArtifact

go/ports/state.go:148

RemoveArtifact(context.Context, string, string) error

Remove only unreferenced scoped metadata, retaining shared content safely. Usage: err := store.RemoveArtifact(ctx, scope, digest).

StateStore.Assign

go/ports/state.go:151

Assign(context.Context, Assignment) (Operation, error)

Atomically bind an install request key, desired revision and supersession of pending work. Usage: operation, err := store.Assign(ctx, assignment).

StateStore.ListOperations

go/ports/state.go:154

ListOperations(context.Context, string, string, string, int, time.Time) ([]Operation, error)

Expire overdue work and page scoped durable progress/results. Usage: operations, err := store.ListOperations(ctx, scope, deviceID, "", 100, now).

StateStore.AuthorizeDownload

go/ports/state.go:157

AuthorizeDownload(context.Context, string, []byte, string, string, string, time.Time) (Artifact, error)

Verify device credential, scope, active operation/lease and deadline before returning metadata. Usage: artifact, err := store.AuthorizeDownload(ctx, deviceID, credentialHash, operationID, digest, leaseID, now).

StateStore.SetPolicy

go/ports/state.go:160

SetPolicy(context.Context, PolicyAssignment) (DesiredPolicy, error)

Atomically bind a normalized replacement and validate every required app assignment. Usage: desired, err := store.SetPolicy(ctx, assignment).

StateStore.GetPolicy

go/ports/state.go:163

GetPolicy(context.Context, string, string) (PolicyStatus, error)

Return consistent scoped desired/reported/compliance state. Usage: status, err := store.GetPolicy(ctx, scope, deviceID).

Artifact

go/ports/state.go:168

type Artifact struct {
    ScopeID         string      `json:"scope_id"`
    SHA256          string      `json:"sha256"`
    PackageName     string      `json:"package_name"`
    VersionCode     int64       `json:"version_code"`
    MinSDK          uint32      `json:"min_sdk"`
    MaxSDK          uint32      `json:"max_sdk"`
    SigningCertificates []string    `json:"signing_certificates"`
    SupportedABIs       []string    `json:"supported_abis"`
    SizeBytes       int64       `json:"size_bytes"`
}

Empty artifact scope is reserved for public bootstrap content; managed APKs always have an explicit scope. Store metadata is immutable for a scope/digest.

Assignment

go/ports/state.go:179

type Assignment struct {
    ScopeID, DeviceID, ArtifactSHA256, IdempotencyKey, OperationID  string
    Now, NotBefore, Deadline                    time.Time
}

DesiredApplication

go/ports/state.go:183

type DesiredApplication struct {
    Artifact    Artifact    `json:"artifact"`
    Revision    uint64      `json:"revision"`
}

Operation

go/ports/state.go:187

type Operation struct {
    ID      string          `json:"id"`
    DeviceID    string          `json:"device_id"`
    Artifact    Artifact        `json:"artifact"`
    Revision    uint64          `json:"revision"`
    State       string          `json:"state"`
    LeaseID     string          `json:"lease_id"`
    LeaseUntil  time.Time       `json:"lease_until"`
    Deadline    time.Time       `json:"deadline"`
    NotBefore   time.Time       `json:"not_before"`
    Attempts    int         `json:"attempts"`
    ReportSequence  uint64          `json:"report_sequence"`
    DownloadedBytes int64           `json:"downloaded_bytes"`
    ErrorCode   string          `json:"error_code"`
    ErrorMessage    string          `json:"error_message"`
    Observed    *InstalledApplication   `json:"observed,omitempty"`
}

OperationReport

go/ports/state.go:204

type OperationReport struct {
    ID, OperationID, LeaseID    string
    Sequence            uint64
    State               string
    DownloadedBytes         int64
    ErrorCode, ErrorMessage     string
    Observed            *InstalledApplication
}

ReportReceipt

go/ports/state.go:212

type ReportReceipt struct {
    ReportID    string  `json:"report_id"`
    Accepted    bool    `json:"accepted"`
    Reason      string  `json:"reason"`
}

ApplicationCompliance

go/ports/state.go:217

type ApplicationCompliance struct {
    PackageName string  `json:"package_name"`
    Revision    uint64  `json:"revision"`
    State       string  `json:"state"`
    Reason      string  `json:"reason"`
}

SyncInput

go/ports/state.go:223

type SyncInput struct {
    DeviceID        string
    CredentialHash      []byte
    Inventory       Inventory
    Sequence        uint64
    ReportedRevision    uint64
    RetainedOperationIDs    []string
    CommandReports      []CommandReport
    Reports         []OperationReport
    NetworkReport       *NetworkReport
    PolicyReport        *PolicyReport
    Now         time.Time
}

Snapshot

go/ports/state.go:236

type Snapshot struct {
    Network         NetworkStatus       `json:"network"`
    Device          Device          `json:"device"`
    Sequence        uint64          `json:"sequence"`
    Desired         []DesiredApplication    `json:"desired"`
    Operations      []Operation     `json:"operations"`
    Commands        []Command       `json:"commands"`
    CommandReceipts     []string        `json:"command_receipts"`
    StoppedOperationIDs []string        `json:"stopped_operation_ids"`
    Receipts        []ReportReceipt     `json:"receipts"`
    Compliance      []ApplicationCompliance `json:"compliance"`
    DesiredPolicy       *DesiredPolicy      `json:"desired_policy,omitempty"`
    PolicyCompliance    []PolicyResult      `json:"policy_compliance"`
}

ReadSeekCloser

go/ports/state.go:251

type ReadSeekCloser interface {
    io.Reader
    io.Seeker
    io.Closer
}

ArtifactStore

go/ports/state.go:261

type ArtifactStore interface {
    // Atomically publish complete immutable bytes and reject digest mismatches or conflicting replacements.
    // Usage: err := store.Put(ctx, digest, verifiedBytes).
    Put(context.Context, string, []byte) error
    // Return a detached seekable snapshot of immutable content; the caller closes the reader.
    // Usage: store, err := filesystem.Open("/var/lib/kylok/artifacts").
    Open(context.Context, string) (ReadSeekCloser, error)
}

ArtifactStore puts complete content atomically by SHA-256 and must reject a digest mismatch or replacement with different bytes. Open returns an immutable snapshot. Only empty-scope bootstrap artifacts are publicly served; managed applications require authenticated device/operation/lease authorization.

ArtifactStore.Put

go/ports/state.go:264

Put(context.Context, string, []byte) error

Atomically publish complete immutable bytes and reject digest mismatches or conflicting replacements. Usage: err := store.Put(ctx, digest, verifiedBytes).

ArtifactStore.Open

go/ports/state.go:267

Open(context.Context, string) (ReadSeekCloser, error)

Return a detached seekable snapshot of immutable content; the caller closes the reader. Usage: store, err := filesystem.Open("/var/lib/kylok/artifacts").

MaxAPKBytes

go/provisioning/apk.go:28

const MaxAPKBytes = 64 << 20

Tools

go/provisioning/apk.go:30

type Tools struct{ APKSigner, APKAnalyzer string }

Metadata

go/provisioning/apk.go:31

type Metadata struct {
    PackageName     string      `json:"package_name"`
    Receiver        string      `json:"receiver"`
    VersionCode     int64       `json:"version_code"`
    MinSDK          int     `json:"min_sdk"`
    MaxSDK          int     `json:"max_sdk"`
    SupportedABIs       []string    `json:"supported_abis"`
    SizeBytes       int64       `json:"size_bytes"`
    TargetSDK       int     `json:"target_sdk"`
    Debuggable      bool        `json:"debuggable"`
    SHA256          string      `json:"sha256"`
    SigningCertificates []string    `json:"signing_certificates_sha256"`
}

APK

go/provisioning/apk.go:46

type APK struct {
    // contains filtered or unexported fields
}

APK retains the exact verified bytes; callers cannot mutate metadata or content.

*APK.Verified

go/provisioning/apk.go:55

// Verified distinguishes an inspected immutable artifact from a zero-value APK.
// Usage: if !apk.Verified() { return errors.New("verified APK required") }.
func (a *APK) Verified() bool

Verified distinguishes an inspected immutable artifact from a zero-value APK. Usage: if !apk.Verified() { return errors.New("verified APK required") }.

*APK.IsDPC

go/provisioning/apk.go:59

// IsDPC distinguishes a verified provisioning-capable host from an ordinary signed application.
// Usage: if !apk.IsDPC() { return errors.New("provisioning host required") }.
func (a *APK) IsDPC() bool

IsDPC distinguishes a verified provisioning-capable host from an ordinary signed application. Usage: if !apk.IsDPC() { return errors.New("provisioning host required") }.

*APK.Metadata

go/provisioning/apk.go:63

// Metadata returns detached verified properties so callers cannot mutate registered identity.
// Usage: metadata := apk.Metadata().
func (a *APK) Metadata() Metadata

Metadata returns detached verified properties so callers cannot mutate registered identity. Usage: metadata := apk.Metadata().

*APK.Bytes

go/provisioning/apk.go:72

// Bytes returns a copy of the exact verified APK content for immutable publication.
// Usage: content := apk.Bytes().
func (a *APK) Bytes() []byte

Bytes returns a copy of the exact verified APK content for immutable publication. Usage: content := apk.Bytes().

Inspect

go/provisioning/apk.go:77

// Inspect snapshots the input before invoking Android's signature verifier and XML decoder.
// Both tools inspect the same bytes that are later registered and served.
// Usage: apk, err := provisioning.Inspect(ctx, signedAPKPath, provisioning.Tools{}).
func Inspect(ctx context.Context, path string, tools Tools) (*APK, error)

Inspect snapshots the input before invoking Android's signature verifier and XML decoder. Both tools inspect the same bytes that are later registered and served. Usage: apk, err := provisioning.Inspect(ctx, signedAPKPath, provisioning.Tools{}).

InspectApplication

go/provisioning/apk.go:83

// InspectApplication verifies a single/universal signed APK without requiring DPC components.
// Usage: apk, err := provisioning.InspectApplication(ctx, applicationPath, provisioning.Tools{}).
func InspectApplication(ctx context.Context, path string, tools Tools) (*APK, error)

InspectApplication verifies a single/universal signed APK without requiring DPC components. Usage: apk, err := provisioning.InspectApplication(ctx, applicationPath, provisioning.Tools{}).

Origin

go/provisioning/apk.go:307

// Origin accepts an HTTP or HTTPS origin using a domain name or IP address.
// Route prefixes, credentials and token-bearing URLs are unsupported.
// Usage: origin, err := provisioning.Origin("http://192.168.1.5:8080").
func Origin(value string) (string, error)

Origin accepts an HTTP or HTTPS origin using a domain name or IP address. Route prefixes, credentials and token-bearing URLs are unsupported. Usage: origin, err := provisioning.Origin("http://192.168.1.5:8080").

*APK.Path

go/provisioning/apk.go:317

// Path returns the content-addressed public bootstrap route for these verified bytes.
// Usage: route := apk.Path().
func (a *APK) Path() string

Path returns the content-addressed public bootstrap route for these verified bytes. Usage: route := apk.Path().

*APK.Handler

go/provisioning/apk.go:321

// Handler serves this verified APK only at its immutable GET/HEAD bootstrap path.
// Usage: bootstrapServer.Handler = apk.Handler().
func (a *APK) Handler() http.Handler

Handler serves this verified APK only at its immutable GET/HEAD bootstrap path. Usage: bootstrapServer.Handler = apk.Handler().

*APK.QR

go/provisioning/apk.go:342

// QR returns secret JSON. Hosts must not publish or log the payload.
// Usage: payload, err := apk.QR(bootstrapOrigin, map[string]string{"kylok.server": apiOrigin, "kylok.enrollment_token": token}).
func (a *APK) QR(publicURL string, extras map[string]string) ([]byte, error)

QR returns secret JSON. Hosts must not publish or log the payload. Usage: payload, err := apk.QR(bootstrapOrigin, map[string]string{"kylok.server": apiOrigin, "kylok.enrollment_token": token}).

Version

go/version.go:14

// Version identifies this SDK's source package, independently of its host.
// Usage: version := kylok.Version().
func Version() string

Version identifies this SDK's source package, independently of its host. Usage: version := kylok.Version().

ProtocolVersion

go/version.go:18

const ProtocolVersion uint32 = 1

ProtocolVersion is the current wire version. Development versions must be paired from the same source revision; the number alone is not compatibility.