Generation And Boundaries
Stable ACL output, label handling, function-call placeholders, secret hygiene, and ownership boundaries.
Generation And Boundaries
ACL is useful for product configuration because it keeps configuration readable and structured while leaving sensitive value resolution to the host component.
Generation Behavior
| Behavior | Current implementation |
|---|---|
| Attribute order | Attributes are sorted by key during generation. |
| String escaping | Quotes, backslashes, newline, carriage return, and tab are escaped. |
| Lists and objects | Values are generated inline. |
| Function calls | Calls are preserved as syntax, for example env("PROVIDER_API_KEY"). |
| Labels | Output writes every label in its native ACL block header. |
| Document root shape | Root assignments remain assignments for every value kind; one-attribute blocks with distinct block and attribute names retain braces. |
Native ACL is the only output mode. Neither SDK provides a label-as-attribute generator mode, and Node rejects generator options instead of silently producing a different document shape.
Canonical Bytes And Digests
Use canonical_bytes / canonical_digest in Rust and canonicalBytes /
canonicalDigest in Node when configuration is signed, stored, or compared.
Canonical output uses UTF-8, LF line endings, exactly one final newline, sorted
portable attribute and object keys, and last-value-wins duplicate object keys.
These base APIs preserve block, label, list, and function-argument order.
After schema admission, Rust
canonical_bytes_with_schema / canonical_digest_with_schema and Node
canonicalBytesWithSchema / canonicalDigestWithSchema can recursively
normalize occurrences of a declared block name whose schema rule marks it
unordered. Matching blocks are compared by canonical UTF-8 bytes and replace
only their original slots. Other names, unknown blocks, labels, lists, calls,
and unmarked blocks remain ordered. The schema-aware APIs use the schema only
as normalization metadata; they do not perform admission.
Finite numbers use ECMAScript shortest-round-trip formatting, including 0 for
negative zero. Unicode scalar sequences are preserved without normalization.
The digest format is sha256:<64 lowercase hexadecimal characters>.
Secret Hygiene
Store references, not secrets:
providers "provider" {
api_key = env("PROVIDER_API_KEY")
base_url = env("PROVIDER_BASE_URL")
}Do not commit concrete API keys, bearer credentials, or private endpoints into
ACL examples or product configuration. The ACL crate preserves env(...) as a
function call; the component that loads the configuration decides how to resolve
it.
Ownership Boundary
ACL owns:
- parsing text into AST
- generating text from AST
- value constructors and document builders
- parser diagnostics
- declarative document-shape schemas and bounded validation reports
- base and schema-aware canonical bytes and digests
- language-neutral config shape
The host component owns:
- defining the trusted schema at each product boundary
- validating domain rules beyond document shape
- evaluating function calls
- resolving environment variables or secret-store references
- applying defaults
- converting AST values into product-specific typed configuration
- enforcing policy decisions
Relationship To A3S Components
A3S Code, A3S Sentry, and other A3S components can use ACL as a reviewable configuration format. Each component should keep its schema and evaluator local to that component instead of making ACL a global policy engine.