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
1 change: 1 addition & 0 deletions docs-site/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export default defineConfig({
},
{ label: 'Cypher Query Language', slug: 'guide/cypher-guide' },
{ label: 'Graph Construction', slug: 'guide/graph-construction' },
{ label: 'Move portable projects', slug: 'guide/portable-projects' },
{ label: 'Analytics Integration', slug: 'guide/analytics-integration' },
{ label: 'Visualization examples', slug: 'guide/visualization' },
{ label: 'Exploratory Analyst', slug: 'guide/exploratory-analyst' },
Expand Down
1 change: 1 addition & 0 deletions docs-site/scripts/sync-content.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const PAGES = [
'guide/tutorial.md',
'guide/cypher-guide.md',
'guide/graph-construction.md',
'guide/portable-projects.md',
'guide/analytics-integration.md',
'guide/visualization.md',
'guide/exploratory-analyst.md',
Expand Down
5 changes: 5 additions & 0 deletions docs/guide/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ trees.
| [Quick Start](quickstart.md) | First graph in five minutes |
| [Tutorial](tutorial.md) | Step-by-step walkthrough |
| [VS Code extension](vscode-extension/) | Explore projects, run Cypher, and pair with coding agents inside your editor |
| [Move projects with portable project v2](portable-projects.md) | Verify and move immutable projects locally, air-gapped, or through OCI |

## Everyday workflows

Expand All @@ -31,6 +32,10 @@ Build graphs programmatically using the Python API.
### [Analytics Integration](analytics-integration.md)
Export graphs to NetworkX, igraph, and pandas for further analysis.

### [Move projects with portable project v2](portable-projects.md)
Preview, export, verify, import, selectively share, and promote immutable project
packages without copying live storage state or committing graph data to Git.

### [Visualization examples](visualization.md)
Comparable Plotly, Jaal, PyVis, Cytoscape.js, and Sigma.js paths over one shared
real-data GraphForge projection.
Expand Down
155 changes: 155 additions & 0 deletions docs/guide/portable-projects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Move projects with portable project v2

Portable project v2 is GraphForge's primary workflow for moving a project
between workspaces, machines, and registries. It packages one immutable project
generation with a canonical semantic identity. Use it for local copies,
air-gapped transfer, selective sharing, and OCI promotion.

> **Never copy, archive, synchronize, or publish a live `.graphforge/`
> directory.** It contains generation pointers, journals, locks, leases, and
> other runtime state that are not an interchange contract. Do not commit graph
> or source data, `.gfpb` bundles, `.gfproject/` packages, imports, exports, or
> materialized project state to Git. Keep those paths ignored and move them with
> portable-v2 instead.

The Rust engine owns selection, packaging, verification, import, and OCI
behavior. Python, Node, and the CLI are thin projections of the same operations
and return the same package identity, selection receipt, state classification,
progress, and typed failures.

## Choose the package you intend to share

Preview before exporting. A preview is content-free: it reports the package
class, dependency closure, omissions, redactions, estimated size, and selection
fingerprint without copying payload bytes.

Built-in profiles cover:

- `complete`, for a clean project round trip;
- `ontology-only`, for ontology plus its required bounded metadata;
- component-selective data, artifacts, or non-secret settings; and
- deterministic graph/data subsets with an explicit closure and redaction
policy.

An ambiguous selector or missing dependency fails. GraphForge never widens a
selection silently. Selective packages do not imply graph merge or ontology
adoption; they require an explicit class-specific consumer.

```text
graphforge portable preview --current --profile complete --strict
graphforge portable export --current --profile complete \
--format bundle --output transfer.gfpb
```

Use `--checkpoint NAME` instead of `--current` to package a named immutable
checkpoint. For inspectable directory form, use `--format expanded` and a
`.gfproject` destination. Expanded and bundle representations have different
transport digests but verify to the same semantic package digest and selection
receipt.

## Verify before use

Full verification is required before import or promotion:

```text
graphforge portable verify --input transfer.gfpb --mode full
```

`--mode inspect` checks bounded structure only. It is useful for inventory, but
it does **not** report content as cryptographically verified. A full report
keeps these states separate:

- **completeness**: required structure and declared participants are present;
- **integrity**: every claimed byte and semantic digest matches;
- **compatibility**: versions, capabilities, schemas, and dependencies are
supported; and
- **authenticity**: an optional explicit signer/trust policy succeeded.

A digest match proves content integrity, not publisher identity or authority.
Package identity (`package_digest`) describes selected logical content;
transport identity describes exact bundle bytes or an OCI manifest. Neither is
the source generation or the imported project's new generation.

## Import a complete package

Import only into a new, empty, or pristine initialized destination, using a
caller-owned idempotency key:

```text
graphforge portable import --input transfer.gfpb \
--idempotency-key 018f0f4e-7f4d-7c24-8f8f-8cbab5f47001
```

GraphForge fully verifies before admitting the destination, streams content
through bounded buffers, publishes one durable generation atomically, and then
reopens it. Corruption, cancellation, resource failure, or a crash leaves the
old-or-new authoritative state and no partially published project. Retrying the
same operation identity is safe. Complete import rejects selective packages
without mutating the destination.

## Local and air-gapped transfer

For local or removable-media transfer:

1. Preview the pinned generation and review omissions/redactions.
2. Export a `.gfpb` bundle or `.gfproject/` expanded package.
3. Record the package digest and selection fingerprint separately from the
file/media checksum.
4. Copy the completed portable package—not the live project directory.
5. Run full verification on the receiving machine before import or selective
consumption.

The workflow needs no registry, server, cloud account, or signature service.
Apply normal access controls to the completed package; selection protects only
what was intentionally omitted or redacted.

## Promote through OCI by digest

OCI Distribution is an optional transport adapter. Publish verifies the local
package before upload; pull verifies downloaded content before publishing the
destination.

```text
graphforge portable publish-oci --package transfer.gfpb \
--registry ghcr.io --repository example/graphforge-projects --tag candidate

graphforge portable pull-oci --registry ghcr.io \
--repository example/graphforge-projects \
--reference sha256:OCI_MANIFEST_DIGEST \
--expected-digest sha256:PACKAGE_DIGEST \
--destination received.gfpb
```

Tags are mutable discovery references. Resolve a tag, record the returned OCI
manifest digest, and promote or pull by that digest. Keep the GraphForge package
digest separate: it remains stable across expanded, bundled, and OCI forms.

Credentials are caller-owned and must come from a secure provider or process
environment. Never put credentials in a package, command transcript, receipt,
error report, or progress event. HTTPS is the default. `--insecure-http` is only
for a disposable, isolated local registry and is never a production fallback.

Optional signature attachments establish authenticity only when an explicit
signer/key policy is evaluated. Unsigned content may be integrity-valid while
authenticity is absent.

## API map

All surfaces call the same Rust authority:

| Workflow | Rust API authority | CLI |
| --- | --- | --- |
| Preview | `GraphForge::preview_portable_v2_selection` | `portable preview` |
| Export | `GraphForge::export_portable_v2` | `portable export` |
| Inspect / verify | `verify_portable_v2` | `portable verify` |
| Complete import | `GraphForge::import_portable_v2` | `portable import` |
| OCI publish | `publish_portable_v2_oci` | `portable publish-oci` |
| OCI pull | `pull_portable_v2_oci` | `portable pull-oci` |

Python and Node expose equivalent preview, export, verify, import, publish, and
pull methods without wrapper-owned archive, selection, registry, or fallback
semantics. Counts and byte sizes remain lossless at the binding boundary.

For the normative layout, identity, resource, compatibility, and security
contract, see [Portable project v2 architecture](../book/architecture/portable-project-v2.md)
and [ADR 0021](../adr/0021-portable-project-v2.md).
8 changes: 8 additions & 0 deletions docs/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ across Rust, Python, and Node because all three surfaces use the versioned
[canonical fingerprint contract](../book/architecture/canonical-fingerprints-v1.md)
and its shared golden vectors.

Portable project movement is exposed through the Rust-owned preview, export,
verify, complete-import, OCI-publish, and OCI-pull facades. Python, Node, and
the CLI project the same typed receipts and failures; they do not implement
archive, selection, or registry behavior. Start with the user workflow in
[Move projects with portable project v2](../guide/portable-projects.md), then
use the [normative architecture contract](../book/architecture/portable-project-v2.md)
for exact types, limits, identities, and security states.

The shipped immutable provenance, assertion, confidence, evidence, capability,
and algorithm-run surfaces implement the frozen
[Immutable knowledge public API contract](../book/architecture/knowledge-public-api-v1.md). Their
Expand Down