Treetop's early releases prioritize correctness and one explicit contract over backward compatibility. The 0.1.0 contract removes legacy behavior rather than retaining deprecated adapters. Upgrade the coordinated Core, Bundle, REST, SDK, CLI, frontend, and Bundle Action changes together.
A labeler owns a tuple: (fully qualified Cedar resource type, attribute).
App::Host and Other::Host are distinct types; a root-namespace Host is also
an exact type. Entity IDs, namespace wildcards, and arbitrary Rust applicability
predicates are not scopes.
Construct LabelTarget::new("App::Host", "labels") once, handle its validation
error, and return the target from Labeler::target. Implement read-only derive
logic. Use labeler.apply(&mut resource) for controlled direct application; it
checks the resource type and leaves other types untouched.
The registry captures each declaration when built and rejects duplicate tuples
before installation. It indexes validated Cedar types without reparsing them on
requests. For a matching resource it clears all owned attributes before running
any derivation, then applies labelers in registration order. A derivation returning
None leaves its target absent. Equal attribute names on different types have
independent owners. Reloads publish the complete immutable registry as part of
one engine generation, and captured sessions retain their original generation.
Only attributes owned on the actual resource type are server-derived labels.
Other attributes remain trusted application inputs. Registering App::Host.labels
does not remove or validate Other::Host.labels. Policies that rely on derived
labels must constrain the resource type and install the corresponding owner.
Review policies that previously relied on a global attribute-name reservation.
A labeler cannot echo its own incoming output. An earlier labeler cannot consume
a forged value owned by a later labeler on the same type, because the registry
clears every owned output first. Canonical id is reserved on all types.
Bundle and REST label rules use an explicit target object:
{
"target": { "resource_type": "App::Host", "attribute": "labels" },
"field": "name",
"patterns": [{ "name": "prod", "regex": "^prod" }]
}Replace the old rule-level kind and output fields with target.resource_type
and target.attribute. Old keys, unknown fields, missing target components,
invalid Cedar resource types, empty attribute names, and reserved outputs are
errors. Shared names on disjoint types require separate rules, not a dispatcher.
Set bundle and module manifests to format_version = 2, then rebuild and re-sign
bundles after migrating their configuration. Old archives and signatures are rejected.
- Replace custom
applies_toandoutputmethods withtargetreturning a validatedLabelTarget. Create one labeler per exact target. - Pass the validated target to
RegexLabeler::new(target, field, rules). - Replace
UserPolicieswithPolicyCandidates; replace its deprecated action aliases withcandidate_actionsandcandidate_actions_by_name. Candidate listings do not evaluate Cedar conditions and never authorize operations. - Supply every policy-version field:
hash,loaded_at,label_set, andgeneration. Use explicit null when no label-set identifier exists. Generation is an unsigned 64-bit value local to one engine instance. Omission is an error.
Old-server defaults, wildcard scopes, and deprecated label APIs are removed from the coordinated new contract. Candidate revisions are pinned for integration before publication.