> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Saved results

> Keep the exact result a reader inspected as a dataset version, from an app or the CLI

Save the exact accepted result a reader inspected as a dataset version that other
systems read. Declare a query dataset and save the result through a reviewed
request. Saving does not rerun the calculation.

## Declare a query dataset

Declare the dataset from its complete query and bind it to the application's
`datasets` resource slot. The native analyzer derives its columns, nullability,
logical formats and source set; code generation commits its field identities.
There is no second row schema to maintain.

```ts bijection/datasets.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { defineDataset } from "@bijectionhq/datasets";
import { regionalSales } from "./analytics";

export const report = defineDataset({ key: "report", source: regionalSales });
```

## Expose the save operation

Expose the save operation with its capability. The dataset keys and each public
route are explicit; module or export names do not select a save owner. For a
component installed as `datasets`, its root publishing module includes:

```ts bijection/features/datasets.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { savedResultDiscovery } from "@bijectionhq/datasets/application";
import { exposeOperation } from "@bijectionhq/operations/server";
import { makeFunctionReference } from "bijection/server";
import { components } from "../_generated/api";

// This module also exports the authenticated datasetsApplication readers.
export default exposeOperation(
  "saveResult",
  components.datasets.transfers.saveResult,
  savedResultDiscovery({
    datasets: ["datasets/report"],
    reservation: makeFunctionReference("features/datasets:beginUpload"),
    preparation: makeFunctionReference("features/datasets:keepResult"),
    publication: makeFunctionReference("features/datasets:uploadStatus"),
  }),
);
```

Client generation checks these routes against their public calling contracts and
requires each key to name a dataset kept from results. The containing
application supplies membership and row authorization through its ordinary
dataset readers.

## Save from your app

The generated workspace exposes a typed dataset client. Its save handle uses
ordinary Operations endpoints; acceptance and dataset publication remain
separate. Pass the original nonces again when retrying an interrupted
preparation.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
const saves = workspace.datasets.datasets.report;
const request = await saves.prepareSave(displayedResult, {
  nonce: saveNonce,
  preparation_key: preparationKey,
});

// Keep request.key before submission. Preparation fixes the candidate reviewed
// by this interaction; submission must name that exact candidate.
const prepared = request.prepared;
if (!prepared) throw new Error("The save was not prepared");
const submission = await request.submit(prepared.candidate_digest);
if (submission.kind === "committed") {
  const publication = await request.followPublication();
  if (publication.kind === "published") {
    console.log(publication.version.version_id, publication.version.storage);
  }
}
```

A **result** is the immutable accepted content of one run output. A **request**
fixes one intention; preparation produces its immutable **candidate**. A
committed operation names an upload. **Publication** records that upload's exact
dataset version. Committed acceptance alone does not mean that version exists or
that the caller can read it.

Restore a saved key synchronously with
`workspace.datasets.datasets.report.restoreSave(key)`. Restoring constructs a
local handle and performs no network request. `inspect()` observes the original
Operations request. `followPublication()` inspects its acceptance and observes
only the exact upload returned by its committed receipt. It never chooses the
newest version or submits work.

Submission returns `committed`, `refused` or a pending review. A transport error
does not establish which outcome occurred: inspect the original key before
retrying submission with its original candidate digest. A null inspection
outcome is unresolved; it is not a refusal or evidence that a new request is
needed.

`followPublication()` returns `not_accepted`, `published`, `publication_failed`,
`stopped` or `unavailable`. Its finite deadline covers both request inspection
and publication observation. Ending that wait leaves server work recoverable;
restoration never resumes a submission implicitly.

Preparation keeps the exact result file under its upload reservation. Retrying
with the original nonces reuses that slot, file and operation request. Saving
sends no browser row array. A file already kept for that slot can remain
recoverable after the original result expires; current authorization and erasure
rules still apply.

## Save an exact application snapshot

A retained snapshot can supply a complete public paginated query instead of a
transient result. Declare the destination's columns and its one authorized
query:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export const snapshotReport = defineDataset({
  key: "snapshotReport",
  schema: { region: v.string(), amount: v.int64() },
  origin: { kind: "query", from: ["reports:rows"] },
});
```

Expose `keepSnapshotResult` from `datasetsApplication` and add
`snapshotPreparation: makeFunctionReference("features/datasets:keepSnapshotResult")`
to the save operation's `savedResultDiscovery` declaration. Include the
destination's slot-qualified identity, such as `datasets/snapshotReport`, in
`datasets`. Client generation checks the action's complete calling contract;
runtime invocation still enforces its arguments and authority.

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { snapshotQuerySource } from "bijection/browser";

const source = snapshotQuerySource(
  snapshot,
  api.reports.rows,
  { minimum: 9007199254740993n },
  { retentionSeconds: 86400 },
);
const request =
  await workspace.datasets.datasets.snapshotReport.prepareSnapshotSave(source, {
    nonce: saveNonce,
    preparation_key: preparationKey,
  });
// Review and submit request.prepared.candidate_digest as above.
```

The generated query reference supplies its exact calling contract. The query
returns the ordinary paginated result, including optional `splitCursor` and
`pageStatus` metadata; a `SplitRequired` result refuses the export because its
page may be incomplete. Native custody supplies `paginationOpts` and retains its
cursor. Preparation advances bounded pages, then creates the Operations
candidate only after the complete protected CSV is ready. It never submits the
operation automatically.

Retain `source` and both nonces before preparation. After an interrupted reply,
repeat them unchanged. The export retains its own source hold for the original
requested lifetime, up to 31 days; retries cannot renew it. Current source and
destination authorization still apply to every page and publication. An export
admits at most 32 pages of 128 rows and 32 MiB; exceeding a bound refuses the
complete export. `cancelSnapshotResult` ends only the caller's original waiting
slot export; accepted dataset versions keep their own custody.

## Save from the CLI

The CLI uses the same public calls and its ordinary request journal:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection dataset save-result submit report --result RUN#rows \
  --operation features/datasets:saveResult --request-id 019a0000-0000-7000-8000-000000000001
# Inspect the prepared candidate, then submit that exact candidate:
bijection dataset save-result submit report --request-id 019a0000-0000-7000-8000-000000000001 \
  --candidate-digest CANDIDATE_DIGEST --confirm
bijection dataset save-result status report --request-id 019a0000-0000-7000-8000-000000000001 --wait 30s --format json
```

`--result` names the run and one output as `<run>#<output>`; omit `#<output>` when
the run has exactly one output. The CLI retains the run, output and accepted
result before reserving an upload, and compares a repeated `--result` to that
custody. A request ID is a UUIDv7; omit it on the first preparation to generate
and retain one automatically.

After an interrupted reply, reuse the original request key. Confirmation and
status need no result selector or current feature lookup: the retained request owns
its original preparation and capability. An ended status wait preserves that
request. When multiple save owners match, select the exact public reference with
`--operation`.

For a snapshot source, encode the source with `bijectionToJson` from
`bijection/values` before writing `snapshot-source.json`. This preserves native
integers and binary query arguments. Use the same save and status commands:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection dataset save-result submit snapshotReport --snapshot @snapshot-source.json \
  --operation features/datasets:saveResult --request-id 019a0000-0000-7000-8000-000000000002
# Inspect, then submit the exact prepared candidate:
bijection dataset save-result submit snapshotReport \
  --request-id 019a0000-0000-7000-8000-000000000002 \
  --candidate-digest CANDIDATE_DIGEST --confirm
```

`--snapshot` and `--result` are mutually exclusive. The CLI retains the source's
original bytes and routes before reserving its upload. Retrying with the same
request ID resumes that finite export; it never reloads a source file
implicitly, changes the generation or renews the deadline. Incomplete export
responses never create an Operations candidate. The original source can also be
resumed through the ordinary retained-request inbox.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.