Customer vector registry
CustomerVectorRegistry records the vector IDs your application plans to write
and derives a perimeter from the verified customer evidence log. It uses your
existing EvidenceJournalStore; there is no separate history, default database
or DataPrism-hosted copy.
An ID in this view means a write was planned. It does not establish that the provider stored the vector or that the vector still exists.
Capture before the provider write
import { CustomerVectorRegistry } from "@dataprism/sdk/evidence";
const vectors = new CustomerVectorRegistry({
tenantId: "tenant-42",
scopeId: "production-documents",
store: customerDatabaseAdapter,
});
const target = {
providerInstanceId: "production-search-index",
namespace: "documents",
};
await vectors.recordWriteIntent({
...target,
vectorIds: pendingVectors.map((vector) => vector.id),
});
// Keep vector values and provider credentials in your own integration.
await customerVectorClient.upsert(pendingVectors);
const perimeter = await vectors.enumerateRecordedPerimeter(target);
// Retain perimeter and its checkpoint in your customer environment.Await capture successfully before attempting the provider write. If capture fails, stop that write sequence. If the provider call fails or the process exits after capture, the planned IDs remain in the log. This conservatively retains IDs that may need later inspection, including IDs the provider never stored.
The helper does not invoke a vector provider. Your integration must map the recorded target and IDs to the actual write request. Confirmed write observations, provider responses and deletion are separate integrations.
Identity and intent entries
providerInstanceId is an opaque, customer-defined identifier for one provider
account and index or collection. A vendor name alone is not sufficient. Keep
the mapping to the real target and credentials in your environment, and do not
reuse the identifier for a different target.
namespace is required. Use "" for that instance's default namespace; it is
different from a missing namespace or a namespace containing a space. Provider
instance identifiers, namespaces and vector IDs are preserved exactly, without
trimming or Unicode normalization. Vector IDs must be nonempty strings, and an
intent must contain at least one ID. Additional fields are rejected. Do not put
content, credentials or signed URLs into identifiers.
Each vector.write.intent entry uses the existing evidence-entry profile:
outcome: "succeeded"describes successful intent capture, not a provider write.source.kind: "sdk-observed"identifies the capture source.source.coverage: "partial"makes no claim of provider-wide completeness.source.collectedAtis the customer's observed time, not established time.detailscontains onlyproviderInstanceId,namespaceandvectorIds.
Retries and enumeration
If a database commits an append but its response is lost, retrying capture can
append another intent. Both capture attempts remain visible. Enumeration returns
each distinct ID once, sorted by JavaScript's default string order; it does not
claim exactly-once capture or exactly-once provider writes. Concurrent appends
can raise EvidenceJournalConflictError, which the caller must handle before
continuing to provider work.
enumerateRecordedPerimeter() verifies the log through the head captured at the
start of the read. It returns the selected target, tenant and scope, sorted IDs,
that head's sequence and hash as checkpoint, and
basis: "recorded-write-intents". An empty log has a null checkpoint. A populated
log with no matching intents still returns its verified checkpoint and an empty
ID list. Later appends belong to a later enumeration; retain the returned result
if subsequent work must use that exact perimeter.
Malformed vector.write.intent entries cause VectorRegistryError, including
entries for other provider instances or namespaces. Invalid intent outcomes,
source labels and extra detail fields are rejected rather than skipped. Evidence
integrity failures propagate from the evidence log. Inputs are copied before
storage is read, and the returned perimeter, ID array and checkpoint are frozen.
Both methods accept an AbortSignal in their second argument. Cancellation after
an append commits can reject the call while leaving the intent retained, just
like a lost response.
What remains outside the perimeter
The result covers recorded intents through its checkpoint. It is not a current provider inventory and cannot include writes that bypass capture. The underlying hash chain detects changes relative to a trusted checkpoint; it cannot prove that unseen events were never dropped or detect a rollback of both the log and its head without an independently retained checkpoint.
Tenant and scope labels isolate this view. They do not prove exclusive ownership of a physical vector or bind it cryptographically to a file's scope key. Before deletion, your integration must handle shared or reused IDs and coordinate live writes. Destroying a file scope key does not establish that external vectors became unreadable.
Enumeration reads and verifies the full log, then builds the selected ID set in
memory. It is not a paginated provider scan. The customer remains responsible
for adapter atomicity, access control, durability, retention, backups and
availability. MemoryEvidenceJournalStore is for tests and examples, not a
durable customer record.

