Architecture session: queue topology, log schema, REC templates, config refinements
- Rename env.toml to env_{dev,qa,prod}.toml for self-documentation; enforce via gitignore
- Config loader selects env file via BEDS_ENV environment variable, defaults to dev
- Set wbid to "ms" in beds.toml
- Define queue topology: rel/rec .read .write .obj, log, adm, mig
- Define log event schema: compound event_id (node.env.guid), parent_id, depth,
level/level_val, resource, service, env, node, file, method, line, trace, message, created
- Add example_rec.toml — canonical self-documenting REC template for future developers
- Add mst_logger_rec.toml — logger collection template derived from log event schema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
449
templates/example_rec.toml
Normal file
449
templates/example_rec.toml
Normal file
@@ -0,0 +1,449 @@
|
||||
# =============================================================================
|
||||
# BEDS REC Template — MongoDB Document Store
|
||||
# =============================================================================
|
||||
#
|
||||
# This is the canonical example template for a REC (document store) collection.
|
||||
# Copy this file, rename it to match your collection (e.g.: users_rec.toml),
|
||||
# and edit the values to define your schema.
|
||||
#
|
||||
# NAMING CONVENTIONS:
|
||||
# -------------------
|
||||
# Template file: {collection_name}_rec.toml
|
||||
# Collection name: {wbid}{CollectionName} e.g.: gaUsers (wbid "ga" from beds.toml [id])
|
||||
# Extension (TLA): _{3-char-identifier} e.g.: _usr
|
||||
# All field names: {field_name}_{tla} e.g.: email_usr, status_usr
|
||||
#
|
||||
# The TLA (three-letter abbreviation) is appended to the collection name and
|
||||
# to EVERY field name within the collection. This convention eliminates all
|
||||
# ambiguity in queries, joins, and log output. BEDS enforces this at template
|
||||
# validation time — templates that violate naming conventions are rejected.
|
||||
#
|
||||
# AUTHOR: beds
|
||||
# VERSION: 1.0
|
||||
# =============================================================================
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# IDENTITY
|
||||
# =============================================================================
|
||||
|
||||
# Template version — increment when the schema changes. Not the BEDS version.
|
||||
version = 1
|
||||
|
||||
# The BEDS node service this collection lives on.
|
||||
# Valid values: "app_server" | "admin" | "segundo" | "tercero" | or any
|
||||
# custom node name defined in your config file.
|
||||
service = "app_server"
|
||||
|
||||
# Storage engine for this template. REC templates always use "rec".
|
||||
# Valid values: "rec" | "rel"
|
||||
# This value is used by BEDS to select the correct adapter at instantiation.
|
||||
schema = "rec"
|
||||
|
||||
# Human-readable name for this template. Used in logging, admin UI, and the
|
||||
# REST API catalog. Must be unique across all templates.
|
||||
template_class = "ExampleCollection"
|
||||
|
||||
# MongoDB collection name. Convention: {wbid}{ClassName} — no underscores.
|
||||
# The wbid is your 2-char corporate identifier declared in beds.toml [id].
|
||||
# Example: wbid "ga" + class "Example" = "gaExample"
|
||||
collection = "{wbid}Example"
|
||||
|
||||
# Three-letter abbreviation (TLA) for this collection — appended to the
|
||||
# collection name and to every field name. Must be unique across all templates.
|
||||
# Example: "_usr", "_ord", "_log", "_ses"
|
||||
extension = "_exa" # exa = example
|
||||
|
||||
# Warehousing destination template name. Set to the name of the COOL storage
|
||||
# template if this collection supports warehousing. Leave empty if not used.
|
||||
wh_template = ""
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# BEHAVIOURAL FLAGS
|
||||
# These flags control what operations BEDS will allow on this collection.
|
||||
# =============================================================================
|
||||
|
||||
# closed_class: when true, only internal BEDS services may instantiate this
|
||||
# template. When false, registered external partners may also access it.
|
||||
# Default: true — restrict access unless you explicitly open it.
|
||||
closed_class = true
|
||||
|
||||
# hard_deletes: when true, DELETE operations permanently remove the record.
|
||||
# When false, DELETE sets status to inactive (soft delete). Soft deletes are
|
||||
# the safer default — records are recoverable.
|
||||
hard_deletes = false
|
||||
|
||||
# updates_enabled: when true, UPDATE operations are permitted on this
|
||||
# collection. When false, records are immutable after insert. Log collections
|
||||
# should always be false.
|
||||
updates_enabled = true
|
||||
|
||||
# auditing: controls which operations generate an audit trail.
|
||||
# Valid values:
|
||||
# "disabled" — no auditing
|
||||
# "destructive" — audit writes and deletes only
|
||||
# "nondestructive" — audit reads only
|
||||
# "full" — audit all operations
|
||||
auditing = "nondestructive"
|
||||
|
||||
# journaling: when true, BEDS records a journal entry for every destructive
|
||||
# operation (create, update, delete) on this collection. Requires the journal
|
||||
# service to be active. Disable for high-volume append-only collections.
|
||||
journaling = true
|
||||
|
||||
# record_history: when true, BEDS maintains a full history of every version
|
||||
# of each record. High storage cost — use only where full history is required.
|
||||
record_history = false
|
||||
|
||||
# default_status: the status value assigned to new records on insert.
|
||||
# Must be a value defined in the BEDS status catalog.
|
||||
default_status = "active"
|
||||
|
||||
# search_status: the default status filter applied to fetch queries when no
|
||||
# status filter is supplied by the caller. Protects against accidentally
|
||||
# returning inactive or deleted records.
|
||||
search_status = "active"
|
||||
|
||||
# record_locking: when true, BEDS applies an optimistic lock on records during
|
||||
# updates to prevent concurrent write conflicts. Enable for collections where
|
||||
# simultaneous updates to the same record are possible.
|
||||
record_locking = false
|
||||
|
||||
# query_timers: when true, BEDS records query execution time for every
|
||||
# operation on this collection. Timer data is published as a metric event.
|
||||
# Recommended true in all environments for performance visibility.
|
||||
query_timers = true
|
||||
|
||||
# primary_key: the field used as the primary key for this collection.
|
||||
# "token" uses the BEDS-generated GUID token (recommended).
|
||||
# "mongo_id" uses MongoDB's native _id field.
|
||||
primary_key = "token"
|
||||
|
||||
# tokens: when true, BEDS generates and manages a GUID token field (db_token)
|
||||
# for every record. This is the externally-exposed identifier — the internal
|
||||
# MongoDB _id is never returned to clients. Strongly recommended true.
|
||||
tokens = true
|
||||
|
||||
# cache_ttl: number of seconds a fetched record remains in the in-process
|
||||
# cache. 0 = caching disabled for this collection. Disable for collections
|
||||
# with high write frequency where stale reads are unacceptable.
|
||||
cache_ttl = 300
|
||||
|
||||
# is_internal: when true, marks this as a BEDS internal system collection.
|
||||
# Internal collections are excluded from the public REST API catalog.
|
||||
# Set true for logging, metrics, audit, and other framework collections.
|
||||
is_internal = false
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# FIELDS
|
||||
# Defines every field in the collection and its data type.
|
||||
# BEDS validates all incoming data against this map before insertion.
|
||||
# Fields not declared here are silently dropped.
|
||||
#
|
||||
# Field name convention: {field_name}_{tla} e.g.: email_usr
|
||||
#
|
||||
# Valid types:
|
||||
# "string" — UTF-8 text
|
||||
# "integer" — whole number
|
||||
# "double" — floating point number
|
||||
# "boolean" — true | false
|
||||
# "object" — embedded document (sub-object)
|
||||
# "array" — flat array of values
|
||||
# "date" — MongoDB Date object (required for TTL indexes)
|
||||
# =============================================================================
|
||||
|
||||
[fields]
|
||||
# System fields — present in every REC template. Do not remove.
|
||||
_id = "object" # MongoDB native document ID — never returned to clients
|
||||
db_token = "string" # BEDS GUID token — the externally-exposed primary key
|
||||
event_guid = "string" # broker event GUID — links this record to its origin event
|
||||
status = "string" # record status (active | inactive | deleted)
|
||||
created = "integer" # epoch timestamp — record creation time
|
||||
accessed = "integer" # epoch timestamp — last read time
|
||||
|
||||
# Application fields — define your schema below.
|
||||
# Remember: every field name must end with the collection TLA (_exa here).
|
||||
name_exa = "string"
|
||||
score_exa = "double"
|
||||
count_exa = "integer"
|
||||
flag_exa = "boolean"
|
||||
tags_exa = "array" # flat array — each element is a string
|
||||
meta_exa = "object" # embedded sub-document
|
||||
sub_exa = "array" # sub-collection — array of objects (see [sub_collections])
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PROTECTED FIELDS
|
||||
# Fields that clients cannot modify or delete. Attempts to update or remove
|
||||
# protected fields are silently dropped (or rejected, depending on config).
|
||||
# Minimally: db_token, event_guid, created, accessed, _id
|
||||
# =============================================================================
|
||||
|
||||
protected_fields = [
|
||||
"_id",
|
||||
"db_token",
|
||||
"event_guid",
|
||||
"created",
|
||||
"accessed",
|
||||
]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# INDEX FIELDS
|
||||
# Authoritative list of every field that participates in ANY index declaration
|
||||
# below. BEDS uses this list to validate queries at submission time — a query
|
||||
# that cannot be satisfied by a declared index is rejected before execution.
|
||||
#
|
||||
# If a field is not in this list, it cannot be used as a query discriminant.
|
||||
# Warehouse indexes are limited to: created, db_token, event_guid only.
|
||||
# =============================================================================
|
||||
|
||||
index_fields = [
|
||||
"_id",
|
||||
"db_token",
|
||||
"event_guid",
|
||||
"status",
|
||||
"created",
|
||||
"accessed",
|
||||
"name_exa",
|
||||
"score_exa",
|
||||
"count_exa",
|
||||
"flag_exa",
|
||||
"meta_exa",
|
||||
]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# INDEX NAME REGISTRY
|
||||
# All explicitly-named indexes (compound, multikey) must be registered here.
|
||||
# Single-field indexes and unique indexes do not require names.
|
||||
# If no named indexes are declared below, set to empty array: []
|
||||
# =============================================================================
|
||||
|
||||
index_name_list = [
|
||||
"cIdx1Exa", # compound index — count_exa + score_exa
|
||||
"mIdx1Exa", # multikey index — tags_exa sub-field
|
||||
]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# SINGLE-FIELD INDEXES
|
||||
# One entry per field. Sort direction: 1 = ascending, -1 = descending.
|
||||
# _id is the default MongoDB index — never declare it here.
|
||||
# If a field is declared here, do NOT also declare it as a compound index field
|
||||
# that is its own single entry.
|
||||
# =============================================================================
|
||||
|
||||
[single_field_indexes]
|
||||
db_token = 1 # token should always be indexed
|
||||
event_guid = 1 # event GUID should always be indexed
|
||||
status = -1 # fetch by status is a common query pattern
|
||||
created = -1 # descending — most recent first
|
||||
flag_exa = 1
|
||||
name_exa = 1
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# COMPOUND INDEXES
|
||||
# Format: index_name = [ [field, direction], [field, direction], ... ]
|
||||
# MongoDB does not use index labels internally — the name is for BEDS only.
|
||||
# The index name must appear in index_name_list above.
|
||||
# =============================================================================
|
||||
|
||||
[compound_indexes]
|
||||
cIdx1Exa = [["count_exa", 1], ["score_exa", -1]]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# MULTIKEY INDEXES
|
||||
# For fields declared as "array" type. MongoDB automatically applies multikey
|
||||
# behaviour to array fields declared in single or compound indexes.
|
||||
# Use dot notation to index a subset of array sub-fields.
|
||||
# The index name must appear in index_name_list above.
|
||||
# Format: index_name = [ [dot.notation.field, direction], ... ]
|
||||
# =============================================================================
|
||||
|
||||
[multikey_indexes]
|
||||
mIdx1Exa = [["tags_exa.label", 1]]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# UNIQUE INDEXES
|
||||
# MongoDB rejects inserts/updates that would create a duplicate value.
|
||||
# db_token should always be unique. Add other fields as required.
|
||||
# Format: field_name = sort_direction
|
||||
# =============================================================================
|
||||
|
||||
[unique_indexes]
|
||||
db_token = 1 # BEDS token is always unique — do not remove
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# PARTIAL INDEXES
|
||||
# Indexes that only include documents matching a filter expression.
|
||||
# More efficient than full indexes for sparse or conditional data.
|
||||
# Format: array of [ [field, direction], [filter_expression] ] pairs.
|
||||
#
|
||||
# Example below: index on meta_exa only where created field exists.
|
||||
# =============================================================================
|
||||
|
||||
[[partial_indexes]]
|
||||
field = "meta_exa"
|
||||
direction = 1
|
||||
filter = { "created" = { "$exists" = true } }
|
||||
|
||||
[[partial_indexes]]
|
||||
field = "meta_exa"
|
||||
direction = 1
|
||||
filter = { "created" = { "$exists" = false } }
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# TTL INDEXES
|
||||
# Automatically delete documents after a specified number of seconds.
|
||||
# Can only be applied to fields of type "date" or arrays of dates.
|
||||
# MongoDB uses the earliest date in an array field to calculate expiry.
|
||||
# Format: field_name = seconds_until_expiry
|
||||
# =============================================================================
|
||||
|
||||
[ttl_indexes]
|
||||
# accessed = 86400 # example: expire records not accessed in 24 hours
|
||||
# # commented out — enable only if TTL expiry is required
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# CACHE MAP
|
||||
# Maps internal field names (schema) to external field names (client-facing).
|
||||
# This is the ONLY mechanism by which schema column names are exposed to
|
||||
# clients. Fields not in the cache map are never returned to clients.
|
||||
# If cache_map is empty, all fields in exposed_fields are returned as-is.
|
||||
#
|
||||
# Format: internal_field_name = "external_label"
|
||||
# =============================================================================
|
||||
|
||||
[cache_map]
|
||||
db_token = "id"
|
||||
event_guid = "eventId"
|
||||
status = "status"
|
||||
created = "createdDate"
|
||||
accessed = "accessedDate"
|
||||
name_exa = "name"
|
||||
score_exa = "score"
|
||||
count_exa = "count"
|
||||
flag_exa = "flag"
|
||||
tags_exa = "tags"
|
||||
meta_exa = "meta"
|
||||
sub_exa = "items"
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# EXPOSED FIELDS
|
||||
# When cache_map is null or disabled, this list controls which fields are
|
||||
# returned to clients. If both cache_map and exposed_fields are null, all
|
||||
# fields are returned. _id and internal system fields should never be exposed.
|
||||
# Leave null if using cache_map — cache_map always takes precedence.
|
||||
# =============================================================================
|
||||
|
||||
# exposed_fields = null # null = use cache_map (recommended)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# BINARY FIELDS
|
||||
# Fields that contain binary data require special handling by the adapter.
|
||||
# List any binary fields here. null = no binary fields.
|
||||
# =============================================================================
|
||||
|
||||
# binary_fields = null
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# REGEX FIELDS
|
||||
# Fields from index_fields that support regex pattern matching in queries.
|
||||
# This does not create an index — it controls when BEDS applies a regex
|
||||
# operand to a query filter. Only declare string fields here.
|
||||
# =============================================================================
|
||||
|
||||
regex_fields = ["name_exa"]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# SUB-COLLECTIONS
|
||||
# Implements 1:M relationships at the document level. A sub-collection is an
|
||||
# array of objects embedded within the parent document.
|
||||
#
|
||||
# Example: a "questions" collection with an embedded "answers" sub-collection.
|
||||
#
|
||||
# Each sub-collection field must also appear in [fields] (to declare its type)
|
||||
# and in [cache_map] or exposed_fields (to control client visibility).
|
||||
#
|
||||
# Sub-collection elements can be inserted or deleted independently without
|
||||
# modifying the parent document's other fields.
|
||||
#
|
||||
# Format:
|
||||
# [sub_collections.field_name]
|
||||
# fields = ["sub_field_1", "sub_field_2", ...]
|
||||
# =============================================================================
|
||||
|
||||
[sub_collections.sub_exa]
|
||||
# These are the fields within each element of the sub_exa array.
|
||||
# They must also appear in [fields] above with their types declared.
|
||||
fields = [
|
||||
"count_exa",
|
||||
"score_exa",
|
||||
"name_exa",
|
||||
"flag_exa",
|
||||
"db_token",
|
||||
]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# WAREHOUSING
|
||||
# Controls data lifecycle management — moving records from HOT (production)
|
||||
# storage to COOL (warehoused) or COLD (archived/CSV) storage over time.
|
||||
#
|
||||
# HOT — live production data
|
||||
# COOL — warehoused, maintains schema, indexing changes allowed
|
||||
# COLD — archived, reformatted to destination schema (usually CSV)
|
||||
# WARM — data being restored from COLD back to HOT
|
||||
# =============================================================================
|
||||
|
||||
[warehouse]
|
||||
# supported: master switch. Must be true for any warehousing to occur.
|
||||
# If false, all warehousing requests for this collection are rejected.
|
||||
supported = false
|
||||
|
||||
# remote_support: when true, allows importing data into this collection from
|
||||
# a remote source outside the BEDS framework (e.g.: a legacy system migration).
|
||||
remote_support = false
|
||||
|
||||
# automated: when true, BEDS will automatically warehouse records when the
|
||||
# qualifier condition is met, on the defined interval schedule.
|
||||
automated = false
|
||||
|
||||
# dynamic: when true, allows on-demand warehousing requests outside the
|
||||
# scheduled interval. Requires override = true to allow custom query filters.
|
||||
dynamic = false
|
||||
|
||||
# interval: how often automated warehousing runs.
|
||||
# Valid values: "D" = daily | "M" = monthly (1st) | "Q" = quarterly | "Y" = yearly
|
||||
interval = "M"
|
||||
|
||||
# override: when true AND dynamic = true, the caller may supply a custom
|
||||
# query filter in the warehousing request, overriding the default qualifier.
|
||||
override = false
|
||||
|
||||
# delete: what to do with source records after successful warehousing.
|
||||
# Valid values: "H" = hard delete | "S" = soft delete
|
||||
delete = "H"
|
||||
|
||||
# qualifier: the filter that identifies records eligible for warehousing.
|
||||
# Format matches a BEDS fetch query — field, operand, operator, value.
|
||||
# The null value below is replaced at runtime with the caller-supplied date.
|
||||
#
|
||||
# This example: warehouse all active records created before a supplied date.
|
||||
[warehouse.qualifier]
|
||||
created = { operand = "null", operator = "lt", value = "" } # empty = caller supplies value at runtime
|
||||
status = { operand = "null", operator = "eq", value = "active" }
|
||||
logical_op = "and"
|
||||
Reference in New Issue
Block a user