public namespace. The shorter
artifacts.headcount is an alias for artifacts.public.headcount; it never
searches other namespaces. Separate publications can use the same table name,
such as artifacts.september.classifications and
artifacts.october.classifications, without sharing data.
Namespaces are stable SQL identities. Folders remain display organization and
do not change a table’s SQL address.
Declared optional inputs
A Plot can declare an optional Artifact and its expected columns in its Perception contract. Only an absent declared table reads as an empty relation. A present table retains its rows and must satisfy the declared column types and nullability. Extra columns are allowed. Missing columns, incompatible types, unavailable publications, denied access, and explicit revision failures remain errors. A missing or incompatible column fails withQL-TB-005, and an unavailable
publication or revision fails with QL-TB-006. Both are FAILED_PRECONDITION.
An undeclared missing table remains an unknown relation.
If the publication inventory cannot be read completely, Query Layer refuses
optional fallback in publication namespaces until the inventory recovers.
The fallback belongs to one Plot request. It does not appear in catalog
listings or change another Plot’s input declaration. Generic SQL results carry
known absent inputs in parable.warning.absent_optional_artifacts. Pane reads
carry the same names in PlotDataMeta.absentOptionalArtifacts. Stored Reports
keep the producer’s warning even when today’s Artifact inventory differs.
Publication revisions
Ordinary SQL, prepared statements, Flight metadata, and catalog discovery read each namespace’s active revision. A correction is a new revision of the same namespace. Queries keep reading the previous active revision until every table of the correction is ingested and someone activates it, so a failed replacement leaves the previous complete dataset in place. A Flight SQL request can read another revision instead, such as a staged correction waiting for QA, the verified tables of a failed revision, the previous revision, or one revision pinned across several queries. Name it in request metadata:Publish a complete dataset
Use these Workspace API operations to make an entire dataset available together:- Call
artifacts.reserveArtifactPublicationwith a namespace, revision ID, expected active revision, and every table’s name, row count, source size, format, and hash. Tables declare no schema: Parable derives it from the upload. A CSV table gets all-String columns, so send Arrow for typed columns. A table whose name, hash, and row count match the expected active revision’s table reuses its stored data: the receipt marks itreused, and it gets no upload URL. - Upload each remaining CSV or Arrow IPC stream directly to its returned storage URL with the required headers.
- Call
artifacts.finalizeArtifactPublicationand pollartifacts.artifactPublicationReceipt. Each table’soutputSchemaappears in the receipt once analysis derives it. - Once every table is ingested, call
artifacts.activateArtifactPublication. Until then, or until you activate it, the revision stays staged and QA can read it by selecting it. Activation checks the caller’s current permissions and switches the namespace to the complete revision in one transaction; it does not query the tables.
retryFailed; corrected inputs require a new revision ID in the
selected namespace. Activation refuses a replacement whose expected active revision has
changed. Activating a revision that is already READY returns its status and changes
nothing, unless the request sets expectedActiveRevisionId to the current active
revision: that switches back to it, which is how you roll back to the previous revision.
artifacts.removeArtifactPublicationRevision removes a staged or failed revision that
is not active and queues cleanup of its storage. artifacts.deleteArtifactPublication
deletes the namespace: queries stop serving it, its slug becomes free for a new
namespace, and durable cleanup of all its stored data is queued. Receipts of a removed
revision or deleted namespace are no longer readable. Cleanup waits for issued upload
URLs to expire.
Publish a table
An uploaded file becomes queryable inpublic after the Workspace:
- Reserves the upload with
artifacts.prepareArtifactUpload, then sends the file directly to the returned signed storage URL using its required headers. - Calls
artifacts.completeArtifactUploadand waits foruploadStatus: ready. Parable verifies the file and saves a bounded sample and an all-String schema. - Reviews that schema, optionally using
artifacts.runArtifactSchemaInferenceorartifacts.updateArtifactDataSchema. - Calls
artifacts.publishArtifactwith a new request ID, then polls the Artifact’spublishWork. The table becomes queryable only when that work succeeds. Values that cannot be converted to the reviewed schema fail publication; correct the schema or source and retry.
Schema inference and the model policy
runArtifactSchemaInference sends the CSV’s header row and up to five data
rows to the model the Workspace’s model policy chooses for schema inference,
on the AI processor that policy allows, and saves the column types it
proposes. By default it runs on Gemini (gemini-3.5-flash-lite) in Google
Vertex AI’s us multi-region, in the Workspace’s own Vertex AI project when it
has one and a Parable-owned Google Cloud project otherwise. The result’s inference names the
model and the processor that ran.
When the policy allows no processor for schema inference, for example because
a Workspace administrator switched Google Vertex AI off, nothing is sent to any
processor. The call still succeeds: the Artifact’s schemaInferenceStatus
becomes skipped_by_policy, the result’s inferenceRefusal names the reason,
and the Artifact keeps the all-String schema from upload. Edit that schema
with artifacts.updateArtifactDataSchema, then publish it as usual.
Upload limits
Each uploaded file can be up to 1 GB. Accepted formats are.csv, .xlsx,
.xls, .numbers, .ods, and .zip. Only CSV supports preview, schema inference,
and publication. Other formats remain storage-only uploads.
An upload URL accepts only the reserved content type and exact size, and Parable
checks the stored file before the Artifact is ready. Expired URLs require a
new reservation. For an ordinary Workspace, file bytes go to the upload URL,
not through the Workspace API.
Protected Workspaces
A protected Workspace keeps its files in a bucket that accepts only objects encrypted with the Workspace’s customer-supplied key (PARABLE-6436). The browser cannot hold that key, soprepareArtifactUpload returns the transport to use:
SIGNED_URL: send the file to the external signed URL with its required headers. Send no Parable cookies or credentials to it.WORKSPACE_PROXY:uploadUrlis the same-origin path/api/sdk/workspace/<slug>/api/artifacts/uploads/<id>/content. Send the file there withPUT, theContent-Typeheader, and the normal session. The web-app proxy forwards the stream touploadArtifactContent.
uploadArtifactContent accepts only a pending reservation of the same
Workspace that the same caller made, before it expires. The caller must still
act in the Workspace: active membership or bare admin. web-api counts the
bytes itself because the proxy does not forward Content-Length. A body that
is shorter or longer than the reserved size gets WA-AF-025, and nothing is
kept. The write is create-only, so a replay gets WA-AF-026 and never replaces
the stored bytes. web-api takes a short key lease from the key broker before
it writes, with a svc=web-api-storage-keys service token, and asks for it again while the
upload runs. When the broker refuses the first lease, the upload stops with the
broker’s code: WA-SK-002 (protection not active, 409), WA-SK-003 (key
refused, 403), or WA-SK-001 and WA-SK-005 (configuration fault, 409).
When the key is unavailable, or the lease ends during the upload, the upload
stops with 503 and WA-SK-004. Nothing is kept. No response contains the key
or the lease.
Each web-api pod admits at most eight protected uploads at once, before it
requests a key lease. Their GCS chunk and read buffers use at most 66 MiB
in total. A full pod returns 503 with Retry-After: 1 without reading
the body or requesting a key.
web-api selects WORKSPACE_PROXY only when the Workspace protection is
ACTIVE and the protected upload gate is on. Otherwise a protected Workspace
gets WA-AF-027 and no reservation. Ordinary Workspaces always get
SIGNED_URL.
The gate is PROTECTED_ARTIFACT_UPLOADS_ENABLED (default off). It requires
STORAGE_KEY_BROKER_URL, the key broker web-api asks for leases. With the gate
on and no URL, web-api stays not ready. The key broker is a web-api that runs
with STORAGE_KEY_BROKER_ENABLED (default off). In local and ephemeral deploy
values, the URL is populated and points to the main web-api over HTTP. With the
broker flag off, protected leases still fail closed. Staging and production
leave the URL unset. The ephemeral demo enables both flags explicitly and uses
the shared ephemeral identity. The URL edges must move to an isolated broker
workload before customer rollout.
It serves leaseStorageKey to svc=query-runner, svc=query-layer, and
svc=web-api-storage-keys callers only, and marks each response no-store.
The svc=web-api-storage-keys token receives 403 outside
/api/internal/storage-keys/. Only the protected upload path mints it, so a
svc=web-api token that web-api sends to another service is never a lease
credential. Any other
web-api refuses every lease with WA-SK-004. query-runner and query-layer
install their key provider from STORAGE_KEY_BROKER_URL before they open a
store. Without it, every protected bucket fails closed.
A protected Workspace never stores new plaintext sample rows in web-db and
never serves stored ones, until the customer accepts that copy. For any
Workspace with a protection row, in any state:
artifactDataPreview,parableArtifactPreview, andrunArtifactSchemaInferencerefuse withWA-AF-027. They never serve or read stored sample rows. The Ponder file view uses the same Parable preview gate and omits the sample when it is refused.- The worker callback drops the sample rows of an analysis result. It keeps the row count and the schema, so the upload completes.
reserveArtifactPublicationandfinalizeArtifactPublicationrefuse withWA-AF-027. Publication producers are not supported for protected Workspaces.
{table} in that namespace.
Artifacts can join other pools. For example, a
published headcount plan can join Provider directory data on a compatible email
column:
A Parable’s data files
A CSV, Parquet, JSON Lines, or gzipped JSON Lines file that a person adds to a composed Parable becomes a table after its check, with no publish step:{parable} is the Parable’s SQL name, the one in parables.{parable}.{plot}.
{table} comes from the file name. The worker reads the whole file to choose
each column’s type, and it calls no model. The developer site describes the
names and the types, in
Artifacts.
Only SQL that runs in the Parable reads these tables. The Parable’s Plots read
them for every person who can open the Parable. Its other SQL reads them only
for a person who can edit its Plots. Query Layer refuses SQL in another
Parable, and Workspace SQL outside every Parable. Catalog listings outside the
Parable do not show its namespace. A Workspace publication cannot take a
namespace that starts with parable_.
Files do not travel with a Release or a Deploy. A Plot that must run in a
Workspace with no such file declares the table as an
optional input.