/** * @license * Copyright 2022-2026 Matter.js Authors * SPDX-License-Identifier: Apache-2.0 */ import type { AsyncObservable, Transaction } from "@matter/general"; import { DataModelPath, Schema } from "@matter/model"; import type { AccessControl, InteractionSettings, Val } from "@matter/protocol"; import type { FabricIndex } from "@matter/types"; import type { ValReference } from "../state/managed/ValReference.js"; import type { ValidationLocation } from "../state/validation/location.js"; import type { RootSupervisor } from "./RootSupervisor.js"; import type { SupervisionMode } from "./Supervision.js"; /** * Value supervisor implements schema-based supervision of a specific value. * * Supervision functions include: * * - Access controls * * - Datatype validation * * - Managed instance generation * * Supervision is implemented via schema-driven runtime compilation. We perform as much logic as possible at startup to * minimize overhead during server operation. * * This means we typically ingest schema, create a compact form of denormalized metadata, and/or generate functions to * perform required operations. */ export interface ValueSupervisor { /** * The schema manager that owns this ValueSupervisor. */ readonly owner: RootSupervisor; /** * The logical schema that controls the value's behavior. */ readonly schema: Schema; /** * Consolidated access control information for the schema. */ readonly access: AccessControl; /** * Perform validation. */ readonly validate: ValueSupervisor.Validate | undefined; /** * Create a managed instance of a value. */ readonly manage: ValueSupervisor.Manage; /** * Apply changes. Does not perform validation. */ readonly patch: ValueSupervisor.Patch; /** * Convert a JS value to the appropriate JS type for the schema. */ readonly cast: ValueSupervisor.Cast; } export namespace ValueSupervisor { /** * {@link Session} values that control supervision. */ export interface SupervisionSettings extends InteractionSettings { /** * The transaction used for isolating state changes associated with this session. */ transaction: Transaction; /** * If this is true, data validation is disabled. This should only be used in contexts where data validation is * deferred. */ acceptInvalid?: boolean; /** * Present on contexts rooted at a ClientNode (peer node). Drives substitution of the * {@link FabricIndex.OMIT_FABRIC} sentinel on fabric-scoped struct writes so the local cache mirrors the * post-write peer state. * @see {@link MatterSpecification.v161.Core} ยง 7.13.6 */ clientPeerContext?: { /** Fabric index the peer assigned to our identity, when known. */ fabricIndexOnPeer?: FabricIndex; }; /** * Controls how per-instance supervision config is scoped. * * - `"global"`: config mutations persist across sessions (used for view and initialization) * - `"local"`: config mutations are session-scoped (default for normal transactions) */ supervisionMode?: SupervisionMode; /** * If true, structs initialize without named properties which are more expensive to install. This is useful * when implementing the Matter protocol where ID is the only value necessary. */ protocol?: boolean; } /** * {@link Session} information that enforces stricter controls based on an authenticated remote subject. */ export interface RemoteActorSession extends AccessControl.RemoteActorSession, SupervisionSettings { /** * If present the session is associated with an online interaction. Emits when the interaction ends. */ interactionComplete?: AsyncObservable<[session?: RemoteActorSession]>; /** * Set to true when the interaction has started and the interactionBegin event was emitted for this session */ interactionStarted?: boolean; } export interface LocalActorSession extends AccessControl.LocalActorSession, SupervisionSettings { /** * If present the session is associated with a local act() invocation. Emits when the act() transaction * commits. */ interactionComplete?: AsyncObservable<[session?: LocalActorSession]>; } export type Session = LocalActorSession | RemoteActorSession; export type Validate = (value: Val, session: Session, location: ValidationLocation) => void; export type Manage = (reference: ValReference, session: Session) => Val; export type Patch = (changes: Val.ReadonlyCollection, target: Val.Collection, path: DataModelPath) => Val; export type Cast = (value: Val) => Val; }