Documentation
¶
Overview ¶
Package event provides an in-process bus for typed events with enrollment, actor and timestamp metadata.
Design ¶
Subscribers can observe lifecycle and command outcomes without being coupled to the service implementation. The bus supports synchronous and asynchronous dispatch and configurable handler-error reporting. Close drains queued asynchronous work. The bus itself has no durable storage.
Events may contain sensitive protocol data. External sinks in server/eventsink apply an explicit projection, and server/audit persists that projection when configured. Direct subscribers must apply their own disclosure policy. The DDM notifier consumes persistent change rows rather than relying on bus delivery.
References ¶
- Decision record 0001: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0001-architecture.md
- Decision record 0006: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0006-mdm-signature-verification.md (CertRotated)
- Decision record 0015: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/research/decisions/0015-push-cert-store.md
- Threat model: https://github.com/deploymenttheory/go-apple-dm/blob/main/docs/security/threat-model.md (Repudiation)
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrClosed = errors.New("event: bus closed")
ErrClosed is returned by Publish after Close.
Functions ¶
This section is empty.
Types ¶
type Bus ¶
type Bus struct {
// contains filtered or unexported fields
}
Bus dispatches events to subscribers. It is safe for concurrent use.
func (*Bus) Close ¶
Close stops accepting events and waits for asynchronous deliveries, or until ctx is done.
func (*Bus) Publish ¶
Publish delivers e to subscribers of e.Type and of All. In synchronous mode it returns the joined handler errors; in asynchronous mode it returns immediately and errors go to the error handler. Async delivery retains context values but outlives request cancellation; Close drains accepted events.
type Event ¶
type Event struct {
Type Type
At time.Time
Enrollment mdm.EnrollmentID
// Actor is who caused the event: "device", "admin", or a system component.
Actor string
// Data carries type-specific detail, for example *mdm.Response for CommandResult.
Data any
}
Event is one occurrence.
type Handler ¶
Handler receives events. Returning an error is reported through the bus error handler but does not stop other handlers.
type Option ¶
type Option func(*Bus)
Option configures a Bus.
func WithAsync ¶
func WithAsync() Option
WithAsync dispatches each Publish on its own goroutine; Close waits for in-flight deliveries. The default is synchronous delivery in subscription order, which keeps tests and audit ordering deterministic.
func WithErrorHandler ¶
WithErrorHandler receives handler errors. The default drops them.
type Type ¶
type Type string
Type names an event.
const ( // Security rejections carry metadata only; never attach credentials or remote errors. EnrollmentDenied Type = "enrollment-denied" IdentityRejected Type = "identity-rejected" CertificateStatusRejected Type = "certificate-status-rejected" PrivateHopRejected Type = "private-hop-rejected" Enrolled Type = "enrolled" // Authenticate accepted for a new enrollment Reenrolled Type = "reenrolled" // Authenticate accepted for an existing enrollment TokenUpdated Type = "token-updated" // TokenUpdate stored CheckedOut Type = "checked-out" // CheckOut received CertRotated Type = "cert-rotated" // enrollment identity certificate changed CommandQueued Type = "command-queued" // command enqueued for an enrollment CommandSent Type = "command-sent" // command delivered to the device CommandResult Type = "command-result" // Acknowledged, Error, CommandFormatError, or NotNow BootstrapTokenSet Type = "bootstrap-token-set" // PushTokenInvalid is a token APNs says will never work again (410). // The enrollment is gone until it re-registers. PushTokenInvalid Type = "push-token-invalid" // PushRejected is a push APNs refused for a reason that is not the // device's: a wrong topic, a mismatched or expired push certificate, the // wrong environment, or a malformed request. It is the event to alert // on, because the cause is usually shared by every device on the topic // and no retry will clear it. PushRejected Type = "push-rejected" DDMChanged Type = "ddm-changed" DDMStatusReceived Type = "ddm-status-received" CertReuseDenied Type = "cert-reuse-denied" // Authenticate presented a certificate another enrollment pinned before EnrollmentImported Type = "enrollment-imported" // record written by MigrationStore.Import UserAuthenticated Type = "user-authenticated" // UserAuthenticate digest accepted, AuthToken issued UserAuthFailed Type = "user-auth-failed" // UserAuthenticate digest rejected or challenge expired // ACMEChallengeValid is a device-attest-01 challenge that passed // verification and policy. ACMEChallengeValid Type = "acme-challenge-valid" // ACMEIssued is a device identity certificate issued through ACME. ACMEIssued Type = "acme-issued" // CertificateRevoked is an irreversible issuer-registry status change. CertificateRevoked Type = "certificate-revoked" // AttestationRejected is an attestation that failed verification, named // the wrong device, or was refused by policy. It is the event to alert // on: a device that fails here is either faulty or not what it claims. AttestationRejected Type = "attestation-rejected" // AdminAction is a mutating admin request that was allowed. Actor is the // principal name and Data names the action, method, path, and the // credential that acted, never the token and never the body. AdminAction Type = "admin-action" // AdminDenied records an administrative request refused by authorization. AdminDenied Type = "admin-denied" // All subscribes to every type. All Type = "*" )
Event types published by the service layer.