Skip to content

Harden bind-text-block: deterministic element resolution + library-immutable item_type guard #900

Description

@jfrench9

Summary

Two hardening items in the new bind-text-block path
(robosystems/operations/roboledger/commands/text_blocks.py). Neither is a
security hole — both paths are tenant-scoped and write-gated — but both are
data-integrity / robustness looseness worth closing before the disclosure
authoring surface goes live in prod.

(a) Non-deterministic element resolution, no structure-membership check

_resolve_element resolves a qname via Element.qname == ... .limit(1) with no
ordering, then bind_text_block stamps the fact with structure_id = body.structure_id + element_id = element.id. Nothing verifies the element is
actually an arc member of that structure, and a qname duplicated across
taxonomies in the tenant schema resolves arbitrarily.

Result: a narrative can be attached to the wrong structure.

Fix: make the qname lookup deterministic/unique, and validate the element
participates in body.structure_id (via associations).

(b) item_type stamp can trip the library-immutability trigger

bind_text_block sets element.item_type = "text_block" on first bind
(text_blocks.py:145-149). If the target element is ever library-owned
(created_by = 'library-seeder'), the UPDATE elements on flush hits the
raise_library_immutable_elements trigger (migration 0002) → P0001, which
surfaces as an uncategorized InternalError → 500 (MCP: generic
command_failed).

Unreachable today: the only library text-block-CAP disclosure structures are
abstract (rejected by the is_abstract guard first), and the only concrete
library concepts are the 5 rs-metric ratios (not text-block). It becomes a live
crash the moment the library ships a concrete text-block concept.

Fix: only stamp item_type when created_by != 'library-seeder', drive the
write through the sanctioned library_resync path, or set item_type at
authoring time in create-taxonomy-block instead of lazily on bind.

Test gap

The bind_text_block command itself has no direct unit test (only the
envelope/dispatch and serialization paths are covered), so the item_type path is
untested.

Found during the v1.6.6 pre-release review.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions