Skip to content

D-016: Address.logical_id is pre-binding CIC instance identity, not derived from key_fields #12

Closed

Description

@sinkog

Summary

Tracking issue for D-016 (`ai/DECISIONS.md`) — no new kernel atom needed for a CIC object to have a stable, provider-independent identity before it is created/bound on any provider. This is already expressible with the existing `Address` atom's `logical_id` field; the only real gap was documentation implying a tighter coupling to `key_fields` than the grammar actually enforces.

Background

Came out of investigating a real bug in `cic-module-oracle-cloud` (`#31` — `Plan()` mis-plans a `DeleteVcn` against a resource that does not exist yet), which raised a bigger question: how does the system distinguish "this object doesn't exist at the provider yet" from "this object exists and has drifted," if the object's own identity today is built from the provider-side ID? A circular dependency if identity == provider ID.

The three concepts

```text
Identity — WHAT type is this? (schemas/atomic/identity.yaml — explicitly "not instance identification")
Address.logical_id — WHICH CIC instance is this? (human-friendly, system-independent)
Address.key_fields — WHERE/HOW is this instance addressed/bound on a provider?
```

Why no new atom (verified against the kernel source, not just docs)

  1. `Address`'s own `constraints.must` only requires ONE of `schema_path`/`api_path`/`logical_id` — `key_fields` is `optional: true`. A `logical_id`-only Address is already valid.
  2. `check_grammar.py`'s only `key_fields` rule (C16) checks `role: key` on every entry — nothing checks that `logical_id` derives from `key_fields`. The "composed into logical_id as ..." sentence in `key_fields`'s own description names itself "the corpus convention," not an invariant.
  3. `ManagedEntity.binding_surface` requires "at least one Address," while `Address`'s own description says "An entity may exist without an address" — resolved once "address" isn't read as exclusively "provider binding": a `logical_id`-only Address satisfies both.

What changed

Three documentation-only clarifications (no schema/grammar change):

  • `schemas/atomic/address.yaml`: `key_fields` description — "composed into logical_id" reworded to "MAY be composed/derived ... (a corpus convention, not an invariant)".
  • Same file: `layers.logical_id` description gains an explicit "MAY exist independently of key_fields" sentence, covering the pre-binding case.
  • `schemas/aggregate/managed-entity.yaml`: `binding_surface` description clarifies the required Address may be purely logical (`logical_id`), not necessarily a provider binding.

Verified: `check_grammar.py --self-test` (49/49), `check_grammar.py` against `schemas/examples/*.yaml` and every `cic-schema-registry` file that uses these atoms this session (Subnet/NetworkSpace/StorageResourceOracleCloud specializations, 0 findings each), `yamllint` — zero new violations (diffed against the pre-edit file: all flagged lines pre-exist, none touched by this change).

Why this matters now

The `cic:network` → `cic:oracle:network` two-tier validation model (domain schema validates domain-level sense; provider specialization validates realizability) needs `logical_id` to stay stable at the domain level regardless of which provider currently holds the binding — letting a CIC object migrate providers without its identity changing.

Out of scope here

  • No Git-based intent/state reconciliation engine design.
  • No code fix for `cic-module-oracle-cloud#31` (tracked separately there).

References

  • `ai/DECISIONS.md` D-016
  • `cic-module-oracle-cloud#31`
  • `cic-schema-registry#154` (the Subnet/NetworkSpace OCI specializations referenced as the two-tier validation example)

Activity

  1. sinkog commented on Sep 29, 2026

    @sinkog
    MemberAuthor

    Fixed in #13 (merged to devel, b5e9d51): D-016 recorded in ai/DECISIONS.md, the three documentation clarifications applied to schemas/atomic/address.yaml (key_fields, logical_id) and schemas/aggregate/managed-entity.yaml (binding_surface). check_grammar.py --self-test (49/49) and against every cic-schema-registry consumer of these atoms, both green. No schema/grammar change -- documentation only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions