Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion .agents/skills/loom-framework/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,43 @@ consumer validation.

## Architecture Boundaries

- `admission.Rate` serializes the maintained token bucket's Allow and complete
rate/burst policy updates. Preserve accrued allowance, clamp on reductions and
never reset quota on reconfiguration. `RateAdmission` owns bounded cooperative
backend checks and safe failures; HTTP and protected endpoint adapters retain
their respective placement and authored error contracts. Grouping, key storage,
distributed policy and retries remain application-owned. Keep the rate model,
fractional accounting tests and generated example aligned.

- `admission.Concurrency` owns local unary permits, live capacity updates and
coherent counters under one mutex. Endpoint exit releases the permit;
cancellation and resizing never do. Existing protected endpoint composition
owns validation/access ordering, and authored errors own transport mappings.
Keep the bounded model under `admission/tla/concurrency` and the runnable
generated example aligned. Streaming lifetime, distributed admission,
adaptive policy, configuration endpoints and metrics backends remain outside
this helper.

- Reusable OpenAPI body, response, and header references share one typed importer
walk. Resolve onto occurrence copies before planning; keep component identity
and annotation edges separate from baseline values. The IR allocates authored
identities before inferred components and reserves their names. Versioned
serializers preserve absent versus explicitly empty reference annotations.
Keep the reusable-reference model and cross-kind round-trip tests aligned.


- OpenAPI import normalizes reference assertions with the target's carrier
context, retaining separate reference identity and local constraints. Persist
rejected intersections for planner and renderer admission. Normalize effective
target nullability through membership before supplying carrier context.
Object overlays use Extend; CompositionBases retains declaration identity for
the OpenAPI allOf reference marker, while the composed shape owns physical
fields. Preserve closed-object key sets and do not remove inherited nullability.
Object field facts
distinguish semantic Required from LayoutRequired on the physical declaration;
named occurrence requirements validate the existing carrier. Keep the
reference-sibling model and generated required-field regression aligned.

- `expr.IsNullable` supplies effective nullability to prepared JSON schema
matching and lowered `JSONShape` descriptions. Nullable null bypasses value
predicates, including enums, while ordinary Any null still obeys its enum.
Expand Down Expand Up @@ -340,7 +377,21 @@ consumer validation.
IR consume this projection; keep required scopes on each requirement's fresh
scheme data and preserve them through Dup. Globally deduplicated transport
schemes do not own OR-branch authentication decisions. Keep union-based
unknown-scope admission and OpenAPI's protocol-specific scope-array rules.
unknown-scope admission. SchemeRequirements binds explicit names to scheme
identity: OAuth scopes must be declared; non-OAuth roles need no inventory.
ScopeFor and RoleFor add to shared Scope requirements. Deep-copy these arrays
on inheritance and include them in requirement identity. Import planning owns
normalized requirement validation; OpenAPI exports both OAuth scope arrays and
non-OAuth role arrays. Keep expr/tla/security_requirements and the generated
credential regressions aligned; role assignment remains application-owned.

- `expr.SchemeExpr.FlowScopes` owns effective OAuth inventories: nil inherits
scheme defaults, nonnil empty replaces them. ScopeNames projects available
names only for requirements and callback discovery. Import, OpenAPI export
and generated OAuthFlow maps retain each flow's names and descriptions. When
any flow overrides defaults, resolve every runtime flow explicitly so the
available-name union cannot leak into inherited inventories. Keep the bounded
model in expr/tla/oauth_flow_scopes aligned; token grants remain app-owned.

- `service.assignClientMembers` owns the service Client receiver: reserve all
authored methods, record synthetic mixed-stream method names, then allocate
Expand Down Expand Up @@ -1395,6 +1446,18 @@ filter, and serialization rules belong here.
branches remain unsupported. `expr.ValuePlan.JSONShape` lowers captured
effective predicates. `codegen/unionjson` projects service or HTTP member
layouts and renders typed adapters; `pkg.MatchUntaggedJSON` owns orchestration.
Runtime DSL branches additionally admit string-keyed map fields (#1041) and
nested untagged unions (#1036); import's narrower admission remains separate.
Lower nested alternatives into `JSONShape.Branches`, traverse their member
policies and preserve exact-one matching at every level. Only internal typed
union contract mismatches become ordinary failed decoder candidates; malformed
descriptions, evaluator errors and opaque codec failures stay fatal. Reject
descriptor cycles that revisit a wire value without consuming a member or
collection element, while retaining recursive object/collection compositions. Lower map values through
`JSONShape.Child`, preserve entry-count rules on named map occurrences, and
visit map values when projecting member spelling, visibility and closed-object
policy. Emit named map validators alongside object/array validators. Current
map schemas constrain values; do not add key-schema semantics here.
Independently require unique schema and actual Go matches with the same identity
in both directions. Do not use numeric widths as schema discriminators, select
the first successful branch, or mutate a destination before matching succeeds.
Expand Down
21 changes: 21 additions & 0 deletions .agents/skills/loom-framework/references/formal-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ The [documentation schema admission model](../../../../expr/tla/documentation_sc
separates valid documentation schemas from unsupported generated codecs and
checks that validation visits cannot leak between those contexts.

## Unary admission

The [concurrency model](../../../../admission/tla/concurrency/README.md) checks
permit retention across cancellation and live capacity updates. It rejects
release-on-cancellation and reset-on-resize candidates. Direct race tests cover
Go exit paths; the generated example checks protected HTTP/gRPC admission.

The [rate policy model](../../../../admission/tla/rate/README.md) checks quota
conservation and coherent rate/burst updates. Direct tests cover fractional
accounting and backend deadlines; generated HTTP checks cover early and
authenticated quota placement. Group storage and distributed policy are external.

## Compilation value ownership

The [service semantic ownership model](../../../../codegen/service/tla/semantic_ownership/README.md)
Expand Down Expand Up @@ -261,6 +273,7 @@ Rendered schema validation and actual decoder behavior are separate obligations.
| Public message ownership, history masking, diagnostic exclusion, transparent wrappers and independent joins | [Public disclosure](../../../../pkg/tla/error_disclosure/README.md); finite owner/message model, with HTTP/gRPC/JSON-RPC unary/SSE/WebSocket wire tests |
| gRPC aggregate error status and detail ownership | [Error contracts](../../../../grpc/tla/error_contract/README.md); bounded branch-order and complete-failure checks, with wrappers and generated unary/streaming mappings tested in Go |
| Nearest raw forwarding boundary and prefix independence | [Forwarded client trust](../../../../http/tla/forwarded_client/README.md); bounded chains, with IP parsing and repeated-header grouping checked in Go |
| Per-scheme security scopes and roles with AND/OR/anonymous alternatives | [Security requirements](../../../../expr/tla/security_requirements/README.md); flattened-name counterexample and generated credential checks |
| Authentication alternatives, optional credential extraction and failed-context isolation | [Credential alternatives](../../../../internal/securitygen/tla/credential_alternatives/README.md); finite extraction/control model, with actual framing and HTTP/JSON-RPC/gRPC wire regressions |
| gRPC pre-frame admission, complete application input, original cancellation and middleware rechecks; ordered AND/OR contexts and failed-branch reset | [Stream admission](../../../../security/tla/stream_admission/README.md); positive and deliberate negative models paired with runtime and generated transport regressions |
| Scalar query/header/cookie absence, defaults and conversion admission | [Scalar binding presence](../../../../http/codegen/tla/scalar_binding_presence/README.md); supplied-empty counterexample, shared decoder and mounted HTTP/JSON-RPC controls |
Expand Down Expand Up @@ -343,3 +356,11 @@ The [discriminator admission model](../../../../http/codegen/openapi/internal/ir
records optional/fallback admission and 3.1 projection. Go tests cover reference
resolution and graph retention outside its Boolean assumptions.
| JSON-RPC envelope ID source, presence and validation ordering | [Envelope ID admission](../../../../http/codegen/tla/jsonrpc_id_admission/README.md); params-first and late-handler counterexamples, shared carrier/CLI validation and mounted unary/SSE/WebSocket controls |

OAuth flow inventories: [independent defaults and overrides](../../../../expr/tla/oauth_flow_scopes/README.md), with a flattening counterexample and generated callback checks.

Schema reference siblings: [conjunction and declaration storage](../../../../internal/openapiimport/tla/reference_siblings/README.md), with rejection, replacement, mutation and occurrence-storage counterexamples.

The [reusable-reference model](../../../../internal/openapiimport/tla/reusable_references/README.md)
checks component identity, occurrence overlays, immutable definitions and bounded
forward-reference/cycle admission across request bodies, responses and headers.
4 changes: 4 additions & 0 deletions .agents/skills/loom-framework/references/repo-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ belong in the `loom` skill and the canonical guides under `docs/`.

## Ownership

- `admission/`: local concurrency and rate budgets, atomic settings updates and
bounded cooperative quota checks; existing protected hooks retain access
ordering, and `http/middleware/rate.go` owns early HTTP admission

- `dsl/`: public DSL functions and DSL-time validation entry points
- `expr/`: evaluated design model, preparation, finalization, and semantic
validation
Expand Down
69 changes: 61 additions & 8 deletions .agents/skills/loom/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,33 @@ fields in the body, map them explicitly, or declare `ErrorNameFromStatus()` on
an HTTP error response with a unique status. Views retain their projected contract.
Generation rejects incomplete mappings; add the missing source and regenerate.

## Unary concurrency admission

Use `admission.NewConcurrency(capacity)` and install `budget.Middleware` through
generated `Endpoints.Use` or protected unary per-method constructors. Share a
budget only across methods that should share a process-local limit; exclude
streams. Declare `overloaded` and map saturation explicitly (HTTP 503, for
example), separately from quota errors. `SetCapacity` accepts positive values,
retains active permits and rejects invalid updates without changing the limit.
Cancellation releases capacity only when the wrapped invocation exits. Export
bounded counts and gauges from `Snapshot`; applications own metrics, update
authorization and any cross-replica policy. See [admission](../../../docs/admission.md).

## Rate and burst admission

Use `admission.Rate` for a local token bucket and `SetPolicy` for an atomic
rate/burst update. Updates retain allowance after old-rate refill, clamp it to a
smaller burst and apply the new rate going forward; unchanged updates never
reset spent quota. `NewRateAdmission(check, timeout)` supplies the backend
boundary. Checks must honor their context deadline and own coherent accounting.
Use HTTP `middleware.RateLimit` for early admission and the control's endpoint
`Middleware` through protected constructors for authenticated quotas. Return a
declared denial error, map 429 plus known Retry-After, and declare/map
`rate_limit_unavailable` for backend failures. Applications own trusted grouping,
bounded key storage and local versus shared quota scope. See
[rate limiting](../../../docs/rate-limiting.md) for the runnable example and update
contract. No streams, automatic retries or fleet-wide policy activation are added.

## Typed background activities

Use `execution.Activity[Input, Output]` for named, typed activity calls without
Expand Down Expand Up @@ -574,11 +601,17 @@ and receive a blocking diagnostic before a design is written. See
[OpenAPI import coverage](../../../docs/openapi-import-coverage.md) for supported
recursive shapes and limitations.

Reusable request body, response, and header references retain component names,
forward aliases, and OpenAPI 3.1/3.2 occurrence summary/description annotations,
including empty strings. Shared definitions remain unchanged. Unused definitions,
cycles and wrong-kind references still block strict import. Re-import and
regenerate to adopt this support.

OpenAPI 3.2 Media Type `description` requires `--allow-lossy`.
`prefixEncoding` remains a strict import error.

If you explicitly accept omitting non-contract
metadata, the documented `allOf` flattening and inline array-item promotion,
metadata, the documented inline array-item promotion,
unrecognized `format` values, or a parameter/header (not schema) `deprecated`
flag the HTTP DSL cannot express per-parameter, add
`--allow-lossy`; it warns on stderr for each omission but still refuses any
Expand All @@ -587,11 +620,12 @@ operations. It reports skipped operations and omitted root members separately.
These root members include servers and unsupported info metadata. Tag metadata,
response summaries, supported serialization, structured examples, and reusable
examples import losslessly. API-key, HTTP basic, HTTP bearer, and supported
OAuth 2.0 schemes also import losslessly. OAuth 2.0 flows must use the same
scope map. Root and operation security requirements retain OAuth scopes and
OAuth 2.0 schemes also import losslessly. OAuth 2.0 flows retain independent scope maps, including empty inventories.
Author flow-local scopes in an optional final block on each flow constructor;
no block inherits scheme-level scopes, while an empty block replaces them. Root and operation security requirements retain OAuth scopes and
AND or alternative semantics. Schemes using the same wire credential share one
payload field while retaining each authentication check. A conjunction whose
schemes require different scope sets is rejected; equal scope sets and separate
payload field while retaining each authentication check. Each scheme retains its own required names: OAuth scopes render with
`ScopeFor`, and non-OAuth roles render with `RoleFor`. Empty lists and separate
alternatives remain supported. Partial import omits unused root security when
every retained operation explicitly overrides it. An anonymous `{}`
alternative renders as `Security()` and an explicit operation `security: []`
Expand Down Expand Up @@ -927,7 +961,14 @@ together; these rules also cover JSON-RPC HTTP metadata, not gRPC metadata.
and decoding require the same unique schema and Go branch; overlapping schemas
fail even when Go numeric widths distinguish them. Nil slices encode as `[]`,
which is ambiguous if multiple array branches admit empty arrays. Put nullability
on the enclosing union, not a branch. Opaque codecs and nested maps are rejected.
on the enclosing union, not a branch. Fields may contain string-keyed maps
with constrained primitive, named object, array or map values. Nullability and
entry-count bounds retain their declared meaning. Regenerate service and
transport code when adopting map fields or nested untagged unions. Every
nested union must have exactly one matching named object/array branch; invalid
or ambiguous rows reject the enclosing candidate, and empty arrays stay valid
unless constrained. Map root branches, tagged nested unions and opaque codecs
remain rejected.
- Explicit discriminator tags control wire values independently of schema and
Go type names.
- Optional object unions generate as pointers; required unions remain values.
Expand Down Expand Up @@ -1212,8 +1253,13 @@ projected onto each scheme's declared scopes, including Basic and API keys.
Callbacks can use `scheme.Validate(grantedScopes)` directly: an unscoped key
alongside a scoped JWT receives no JWT scopes. Shared scopes apply to each scheme
that declares them; undeclared scopes fail design validation. Separate `Security`
alternatives retain their own scope sets. Regenerate endpoints and OpenAPI to
adopt this correction.
alternatives retain their own scope sets. Inside Security, use
`ScopeFor(oauth, "read")` to bind OAuth scopes to one scheme and
`RoleFor(key, "admin")` for non-OAuth application roles. Both are additive to
shared Scope declarations. Role names need no scheme inventory. Non-OAuth
callbacks receive them in RequiredScopes and must validate application-owned
grants; they are not extra wire credentials. Regenerate endpoints and OpenAPI;
non-OAuth required names now export as role arrays.

`CookieTransport(scheme, "", fn...)` is the transport-owned browser-cookie
mode. It emits the security contract without synthesizing a payload field or
Expand Down Expand Up @@ -1638,6 +1684,13 @@ loom example <module-import-path>/design
loom vet <module-import-path>/design
```

OpenAPI 3.1/3.2 imports preserve supported bounds, enums, required property
names and annotations beside local schema references. These refine each use
without changing the shared type. Object-property overlays preserve the base
reference through `allOf`; they may refine inherited fields and add fields to
open objects. Changes to the referenced type or nullability and general schema
intersections remain blocked; see `docs/openapi-import-coverage.md`.

## Canonical Guides

For Pulse applications, read `docs/pulse.md`. Client creation and custom hooks
Expand Down
Loading
Loading