Operations
Operations is inseam’s single named catalog of every action invocable against a running instance. A typed registry of OperationDefinitions with shared input/output validation, principal resolution, an idempotency cache, a rate-limit hook, and audit events — wrapped by an Invoker that every transport (HTTP, CLI, future gRPC, in-process native shell) wraps. Plugins contribute operations under prefixed namespaces.
How it fits
Section titled “How it fits”A registered operation is described once and then invoked many times through the same pipeline:
- Lookup by name (
OperationNotFoundErrorotherwise). - Decode input through the operation’s StandardSchema validator (
InputValidationError). - Resolve principal — kind must be one of
network-owner,host-owner,user,agent,service(elseUnauthorizedError). - Idempotency check (unary mutations only): keyed on
(principal_id, operation, idempotency_key), 24h TTL, replay-with-different-input isIdempotencyReplayError. - Rate-limit through the host-supplied
RateLimiter(RateLimitedError). - Audit prelude —
auditSink.invokedwith the canonical SHA-256 input digest. - Invoke handler; validate output; cache result for idempotent unary mutations; emit
auditSink.completedorauditSink.failed.
Two surfaces, split by package:
@inseam/operations-contract—defineOperation,OperationDefinition,OperationShape,OperationHandler,OperationContext, the framework error classes (InputValidationError,OutputValidationError,UnauthorizedError,RateLimitedError,NotFoundError,IdempotencyReplayError,OperationNotFoundError,InternalError), the wire-error envelope (WireError,WireStreamFrame), and the introspection shape (OperationDescribed). Zero runtime deps; noeffect.@inseam/core/operations—openOperationRegistry,createInvoker,installCoreOperations, the registry-level errors, the per-hostoperationIdempotencyMigration, and theAuditSink/RateLimiterseams.
Key pieces
Section titled “Key pieces”defineOperation({ name, shape, input, output, errors, idempotent, handler })— the contract a plugin or core subsystem implements.- Shapes. V1 ships
unaryandserver-stream.client-streamandbidirectionalare reserved in the vocabulary and rejected byregistry.addat registration time. Streams do not participate in the idempotency cache; anAbortSignalfrom the transport propagates to the handler’sctx.signal. openOperationRegistry({ store, clock, log })— the named catalog.addvalidates prefix and list-field declarations;freezelocks the registry before invocation.createInvoker(registry, { store, clock, log, auditSink, rateLimiter })— wraps the registry with the 7-step pipeline.invokeUnary/invokeStreamare the only entry points transports use.installCoreOperations(registry)— registersoperation.listandoperation.describe, the two introspection operations every instance ships.- Tagged errors. Every operation error implements
OperationError({ readonly _tag: string }) withclass.name === _tag. Handler-thrown errors that are neither framework errors nor declared in the operation’serrorsarray are coerced toInternalErrorand logged ascore.diagnostic.unhandled_operation_error.
Exact signatures: @inseam/operations-contract API · arch/operations/spec.md.
When to use this vs alternatives
Section titled “When to use this vs alternatives”Reach for Operations whenever an action needs to be callable from outside core — by a transport, by another subsystem, by a future remote peer. Naming convention: dot-separated, last segment is the verb. Read-only verbs (get, list, watch, describe) default idempotent: true; everything else defaults to false.
Plugins contribute through a prefix-scoped slot bound to their package name and allowed prefixes; the reserved core prefixes (connection., source., access., principal., network., host., plugin., operation.) are off-limits. *.list operations may declare orderableFields / filterableFields arrays; the registry validates each against the top-level properties of the output JSON Schema at registration time.
If an action is purely internal to a core subsystem and never crosses a transport boundary, a plain function is fine. Operations earns its weight when the action needs validation, audit, idempotency, or remote reach.
See also
Section titled “See also”- LLM summary — dense reference for agents.
- Plugin system — how a plugin acquires its operations slot via
RegistrationContext. - Access — Principal kinds and how transports resolve them before invocation.
- Store — the persistence port the idempotency cache writes through.
arch/operations/design.md— why a single named catalog.arch/operations/spec.md— types, the 7-step pipeline, errors, acceptance criteria.