Skip to content

epic(io): ship portable project v2 packaging verification and promotion #740

Description

@DecisionNerd

Problem

Portable project v1 is one proprietary, fully buffered envelope. It excludes file-backed graph trees, has a 16 GiB ceiling, has no inspectable expanded representation, and offers no first-class integrity checker. The current v2 issue only specifies large graph/files transfer; it does not define the product ergonomics needed to package, inspect, selectively share, verify, or promote a GraphForge project.

Manual directory copies are unsafe, while complete-project export is excessive when a user needs only an ontology, a named data subset, selected artifacts, or selected non-secret settings. A checksum can detect corruption, but it does not establish publisher identity or trust.

Objective

Ship portable project v2 as GraphForge's standard project packaging and promotion surface: one semantic package identity across an inspectable expanded package and a deterministic streaming bundle, first-class verification for both, dependency-aware selective packages, OCI-compatible publication/pull, and thin Python, Node, and CLI parity.

This issue is the canonical portable-v2 epic and close gate under #735.

Research basis and direction

The intended architecture is a GraphForge semantic manifest and package digest shared by two local representations: a BagIt-compatible expanded package and one deterministic, streamable bundle encoding. OCI/ORAS is an optional distribution adapter over that package, not a copy of the live project layout and not a new storage authority.

Product contract

  • A package has one representation-independent content identity derived from its canonical semantic manifest and referenced content digests.
  • Expanded and bundled representations verify to the same package identity and selection receipt.
  • A package describes its class, selected components, dependency closure, compatibility/capability requirements, provenance, omissions, and redactions without host paths, mutable timestamps, runtime-local IDs, credentials, or secret values.
  • Built-in selections cover complete project, ontology-only, component-level data/artifacts/settings, and deterministic graph/data subsets. The manifest shell and explicitly disclosed required dependencies may accompany an only selection; unrelated payload classes may not.
  • Integrity verification hashes all claimed content and fails closed. Structure-only inspection must never report verified.
  • Authenticity/signature verification is an explicit additional policy and must never be inferred from matching hashes.
  • Complete packages import atomically into a clean project. Selective packages have explicit consume/apply semantics and never silently adopt an ontology, merge graph data, overwrite settings, or broaden selection.
  • Python and Node remain thin bindings over Rust-owned selection, packaging, verification, import, and distribution behavior.

Issue ledger and dependency order

Issue Deliverable Direct prerequisites
#783 v2 layout, manifest, identity, compatibility, and conformance specification #736
#741 bounded export to expanded and bundled representations #783
#742 bounded atomic import from expanded and bundled representations #783, #784
#784 integrity/compatibility verifier for both representations #783
#785 component selection and dependency-closure planner #741, #784
#786 deterministic graph/data subset export with referential closure #785
#787 OCI registry publish/pull and optional authenticity attachments #741, #742, #784#786
#744 thin Python, Node, and CLI parity for the complete interchange surface #738, #741#743, #784#787

Every issue above blocks this epic. The epic and each child also remain direct blockers of #735; #745 certifies the final integrated M5 tree.

Acceptance criteria

  • The specification fixes the expanded layout, canonical bundle encoding, media types/extensions, semantic manifest, package digest, compatibility rules, v1 policy, and conformance fixtures.
  • The same selected project state exported expanded and bundled produces the same package identity and selection receipt.
  • A bounded verifier distinguishes structural completeness, cryptographic validity, semantic compatibility, and optional authenticity for both representations.
  • Complete, ontology-only, component-selective, and deterministic graph/data-subset packages are supported without leaking unselected payloads or secrets.
  • Complete imports are atomic; selective consumption is explicit, typed, and cannot silently mutate authority or widen scope.
  • OCI publish/pull is digest-pinned, verifies before upload and after download, treats tags as mutable references, and remains optional for local export/share.
  • Rust, Python, Node, and CLI surfaces pass shared conformance fixtures with lossless counts/sizes, stable errors, cancellation, and progress.
  • v1 reading/writing/deprecation behavior is documented and tested.
  • User, API, architecture, security, and promotion documentation presents this as the primary project movement workflow without suggesting raw live-directory copies or committing graph data to Git.

BDD completion scenarios

Scenario: Expanded and bundled forms have one identity

Given one pinned project generation and selection plan
When it is exported as an expanded package and as a bundle
Then both verify to the same semantic package digest, participant inventory, and omission receipt
And host paths, timestamps, locks, journals, caches, and live pointers do not affect identity.

Scenario: A user shares only an ontology

Given a project containing ontology, graph data, artifacts, and deployment settings
When the user exports the ontology-only profile
Then the package contains the explicit ontology document and required bounded metadata only
And verification proves graph data, artifacts, secrets, and unrelated settings were not included.

Scenario: A user shares a deterministic data subset

Given a pinned graph and a supported stable selection
When a subset package is exported
Then nodes, edges, ontology/schema dependencies, provenance, and referential-closure policy are deterministic and disclosed
And unsupported or ambiguous selectors fail instead of silently widening the export.

Scenario: Corruption never becomes a valid project

Given a changed, missing, duplicate, truncated, traversing, linked, or extra entry
When either representation is verified or imported
Then the operation fails before project publication
And the report identifies the bounded relative participant without exposing unrelated host paths.

Scenario: Promotion preserves identity and trust boundaries

Given a locally verified package
When it is published and pulled through an OCI registry by digest
Then the pulled package re-verifies to the same identity
And tag movement, registry authentication, and optional signature policy are reported separately from content integrity.

Observability

Emit structured phase, bytes, entries, elapsed time, package digest, selection-profile, and typed failure data. Never emit content, secrets, credentials, absolute host paths, or unbounded selectors.

Security and privacy

Fail closed on traversal, link/special-file entries, duplicate normalized paths, decompression/resource bombs, concurrent mutation, unsupported capabilities, secret-bearing settings, registry downgrade, digest mismatch, and ambiguous signature policy. Export preview must disclose exactly what will be included and why.

Testing and documentation

Use shared golden/conformance fixtures across expanded, bundled, and OCI forms; corruption and hostile archive fixtures; bounded-memory large-tree tests; privacy/selection leakage tests; v1 compatibility fixtures; clean import/reopen tests; and binding parity tests. Document local sharing, air-gapped transfer, selective promotion, registry publication, integrity versus authenticity, and recovery.

Non-goals

  • Copying or archiving the live .graphforge/state/ layout.
  • Committing graph/source data, imports, exports, or materialized state to Git.
  • Inventing graph merge semantics or silently applying selective packages to an existing project.
  • Requiring a registry, server, cloud provider, or signature service for local packaging.
  • Treating a digest match as proof of publisher identity, authorization, or policy compliance.
  • A domain-specific archive format or foreign runtime engine.

Related issues

Parent M5 tracker: #735. Final integrated certification: #745. Repository-local lifecycle: #219. Portable v1 history: #229. Ontology document lifecycle: #236 and #237.

Metadata

Metadata

Assignees

No one assigned

    Labels

    coreCore source code changesdocumentationImprovements or additions to documentationenhancementNew feature or requesttestingTest coverage and testing infrastructure

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions