Message options¶
Set inside a message block:
spec.generate_from_map¶
Set on message · Type ParamMapConfig · Number 60028
Generate a FromMap method that converts map[string]string to this message type
Example: TokenRequestParams with key_enum="TokenParamKey" generates:
spec.service_state¶
Set on message · Type StateAnnotation · Number 60035
service_state marks a message as a state root.
Example: option (spec.service_state) = {name: "BaseballState", label: ["state-store"]};
spec.state_eviction_policy¶
Set on message · Type EvictionPolicy · Number 60038
NOT IMPLEMENTED. state_eviction_policy would specify the default eviction
policy for all boundaries in a state root message. No generator reads it;
generation REJECTS it (GEN-ANN-1).
Default: EVICTION_POLICY_NONE.
spec.state_sync_backup_count¶
Set on message · Type int32 · Number 60039
NOT IMPLEMENTED. state_sync_backup_count would specify the default sync
backup count for all boundaries. No generator reads it; generation REJECTS it
(GEN-ANN-1).
spec.state_async_backup_count¶
Set on message · Type int32 · Number 60040
NOT IMPLEMENTED. state_async_backup_count would specify the default async
backup count for all boundaries. No generator reads it; generation REJECTS it
(GEN-ANN-1).
spec.grpc_config¶
Set on message · Type GrpcConfigAnnotation · Number 60042
grpc_config marks this message as a gRPC service's configuration.
tacplus generates a generated.Services message and per-service config state boundaries.
spec.disable_auth_message¶
Set on message · Type bool · Number 60044
disable_auth_message marks a service_state message as not requiring authentication.
RPCs on this state service skip token validation entirely.
Use for state roots that must be reachable before callers have tokens
(e.g., TokenExchangerState, TrustedCaState).
Example: option (spec.disable_auth_message) = true;
spec.subscribe¶
Set on message · Type repeated SubscriptionAnnotation · Number 60045
subscribe declares event-bus topic subscriptions for this state service.
Only valid on messages with option (spec.service_state).
Each entry references a topic field on another service's state root.
Example:
spec.record¶
Set on message · Type RecordAnnotation · Number 60065
record marks this message as a stored record (an event held in full by the
record_store, the record store) and makes it projectable. key = unique id field,
owner = ownership/identity field. A record implies event.
Example:
spec.event¶
Set on message · Type EventAnnotation · Number 60079
event marks this message as an EventBus event: a topic + publish RPC are
generated for it. The producer surface is DECLARED — at least one of c2s
(external clients, via gateway) or s2s (internal services). An internal-only
event is s2s and is NOT exposed externally. spec.record implies spec.event.
Example:
option (spec.event) = {s2s: {}}; // internal-only
option (spec.event) = {c2s: {auth_any_user: true}, s2s: {}};
spec.transformation¶
Set on message · Type repeated Transformation · Number 60085
transformation declares a pure typed conversion of this message into a
derived row type. tacplus generates the derived message, its column
annotations, and its projection_source mappings.
DELIVERY IS NOT DECLARED HERE. A transformation needs no spec.record, no
EventBus topic, and no subscription to generate; conversely a record
delivers and stores with no transformation attached. Retention — the one
piece of delivery state the old timeseries_projection bundled in — lives on
(spec.record).retention.
Repeated — one per oneof variant / derived type.
Example:
option (spec.transformation) = {
name: "SessionRecord"
when: "session"
field: {source: "session.model" cardinality_hint: CARDINALITY_LOW}
};
spec.service_event¶
Set on message · Type ServiceEventAnnotation · Number 60060
service_event declares that this state root's topic publish RPCs should be
exposed through the API gateway. tacplus propagates this to the generated
state service as spec.service_c2s and spec.event_label options.
spec.timeseries_type¶
Set on message · Type TimeseriesTypeAnnotation · Number 60061
timeseries_type opts a message into timeseries table generation.
tacplus generates store-neutral conversion helpers and a gRPC service;
a downstream materializer renders the concrete backend schema.
spec.service_store¶
Set on message · Type ServiceStoreAnnotation · Number 60062
service_store marks a message as a durable key-value store.
tacplus generates a gRPC service with Put/Get/Delete/List RPCs.
The backing store implementation can map these RPCs to replicated storage.
Example:
message CredPair {
option (spec.service_store) = {label: ["state-store"]};
string client_id = 1 [(spec.store_key) = true];
string client_secret = 2;
}
spec.opa_eval¶
Set on message · Type OpaEvalAnnotation · Number 60063
opa_eval marks a message as an OPA policy evaluation input.
tacplus generates a typed S2S RPC on opa for each annotated message.
The entry_point identifies the OPA policy path; the result identifies
the output message in the same proto file.
spec.service_health¶
Set on message · Type ServiceHealthAnnotation · Number 60064
service_health declares a typed health message for a service.
The message MUST embed healthreport.ServiceInstanceHealth as field 1.
The state store keeps the full typed message per service, keyed by
instance_id and extracts .base into the generic health view for gateway.
One service_health message per service package.
spec.per_service_config¶
Set on message · Type bool · Number 60068
per_service_config marks a message whose fields are per-service configuration
slices. Each field name must match a known service package name. tacplus
automatically subscribes each named service to a read-only view of its own
slice from the grpc_config service that owns this message type.
Example:
message TenantConfig {
option (spec.per_service_config) = true;
OAuthTenantConfig oauth = 1; // delivered to "oauth" service
IdentityTenantConfig identity = 2; // delivered to "identity" service
OpaTenantConfig opa = 3; // delivered to "opa" service
}
spec.data_entitlement¶
Set on message · Type RedactOption · Number 60069
data_entitlement: message(type)-level default data-entitlement transform for
the eligible fields of this message. A field-level (spec.redact) overrides it.
Only meaningful for fields that are themselves annotation-eligible (e.g.
anonymize requires string/bytes). Mirrors how a message-level default is
overridden per field; does NOT cascade into nested messages (each message
carries its own default).
spec.config_slice¶
Set on message · Type ConfigSliceAnnotation · Number 60075
config_slice marks a message as one per-service configuration slice with an
explicit owner and scope.
Example: option (spec.config_slice) = {scope: CONFIG_SLICE_SCOPE_TENANT, service_name: "identity"};
Field numbers 60069-60072 retired: the legacy tenant_config_slice/
tenant_config_service/project_config_slice/project_config_service aliases
were removed in favor of config_slice. Do not reuse these numbers.
spec.event_publish¶
Set on message · Type repeated EventPublishAnnotation · Number 60073
event_publish declares that this actor publishes an EventBus topic. The
topic_ref must be a tacplus-validated TopicRef:
"<proto-package>.<topic-message>.<topic-field>".
Because this derives a normal RPC, the annotation carries the normal tacplus
method auth shape for the derived RPC. Set exactly one of method_s2s or
method_c2s unless the surrounding actor context provides an unambiguous
default.
spec.event_watch¶
Set on message · Type repeated EventWatchAnnotation · Number 60074
event_watch declares that this actor watches an EventBus topic. The
topic_ref must be a tacplus-validated TopicRef:
"<proto-package>.<topic-message>.<topic-field>".
Because this derives a normal RPC, the annotation carries the normal tacplus
method auth shape for the derived RPC. Set exactly one of method_s2s or
method_c2s unless the surrounding actor context provides an unambiguous
default.
spec.owner_default¶
Set on message · Type OwnerDefault · Number 60080
owner_default declares what the OWNER of a row of this type may do with it
by default (§4b). The owner is the principal named by this message's
(spec.store_principal) field — a message declaring owner_default without one
has no owner to speak of and is rejected at generation time.
The generated service wrapper enforces it: a method the verb registry
classifies as WRITE that touches a type declaring {write: false} is refused
with PERMISSION_DENIED before the handler runs, and likewise a READ method
touching {read: false}. Absent the option nothing is enforced, so this is
additive to every existing type.
It is a DEFAULT, so it binds only a caller acting as its own principal.
PrincipalScope (below) is the override: a grant carrying a scope wider than
self is not the owner acting on itself and is not refused here.
Example: option (spec.owner_default) = {read: true, write: false};
spec.public_view¶
Set on message · Type bool · Number 60093
public_view marks a message whose fields are split between what may be
shown outside the company and what never leaves it (e.g. a prospect record
rendered to a prospect's page). Every field of such a message must declare
(spec.visibility) — there is no default; an unannotated field fails
generation. tacplus generates, as proto, the message "<T>Public" holding
only the VISIBILITY_SHOW fields (same names and numbers; a SHOW field typed
as another public_view message becomes "<Sub>Public"), and the conversion
that parses T through it, discarding everything else: Go <T>ToPublic, Java
to<T>Public, Rust and Python <t>_to_public, TypeScript <t>ToPublic (Swift and
C# emit no message helpers and get the type only). <T>Public is the only
thing a renderer is handed; no RPC callable without a caller token
(RPC_FLAG_PUBLIC_NO_AUTH, auth_disabled, service_c2d) may carry T itself.
Example: option (spec.public_view) = true;