/** * Saved Workflow library schema. * * A saved workflow is deliberately separate from a v3 run: * - metadata.json is the small mutable index (name/scope/pointers/status) * - revisions/.json is immutable and content addressed * * This module has no dependency on the legacy workflow definition/runtime. * It only reuses the v3 DAG/spec validators, then removes the run-specific * `runId` from the persisted template shape. */ import type { V3Node } from './dag.js'; import type { Spec } from './contract.js'; export { canonicalJsonStringify } from '../../utils/canonical-json.js'; export declare const SAVED_WORKFLOW_METADATA_SCHEMA_VERSION: 1; export declare const SAVED_WORKFLOW_REVISION_SCHEMA_VERSION: 2; export declare const SAVED_WORKFLOW_ID_RE: RegExp; export declare const SAVED_WORKFLOW_REVISION_ID_RE: RegExp; export declare const SAVED_WORKFLOW_CONTENT_HASH_RE: RegExp; export declare const SAVED_WORKFLOW_PARAM_NAME_RE: RegExp; export type SavedWorkflowScope = { kind: 'chat'; chatId: string; } /** Visible across chats owned by the same Lark app/bot, never across apps. */ | { kind: 'global'; }; /** open_id is app-scoped, so ownership must retain the app it came from. */ export interface SavedWorkflowOwner { openId: string; larkAppId: string; } export type SavedWorkflowStatus = 'draft' | 'active' | 'archived'; export interface SavedWorkflowMetadata { schemaVersion: typeof SAVED_WORKFLOW_METADATA_SCHEMA_VERSION; workflowId: string; /** User-facing Unicode name. It is never used as a path segment. */ displayName: string; aliases: string[]; owner: SavedWorkflowOwner; scope: SavedWorkflowScope; status: SavedWorkflowStatus; /** Newest immutable revision, published or not. */ latestRevision: string; /** Revision that `run` uses. Missing means this workflow is draft-only. */ publishedRevision?: string; createdAt: string; updatedAt: string; } export type SavedWorkflowParamType = 'string' | 'number' | 'boolean' | 'object' | 'array'; export interface SavedWorkflowParamDef { type: SavedWorkflowParamType; required?: boolean; default?: unknown; description?: string; /** Sensitive inputs may be supplied at run time but never have a stored default. */ sensitive?: boolean; } export type SavedWorkflowBuiltinContextRef = 'chatId' | 'larkAppId' | 'chatType' | 'rootMessageId' | 'initiatorOpenId'; export interface V3DagTemplate { /** Missing/1 is a legacy selector-based template; new revisions require 2. */ schemaVersion?: 1 | 2; nodes: V3Node[]; } export type V3SpecTemplate = Omit; export interface SavedWorkflowSafety { /** Hash of the normalized human gates, protecting against silent gate weakening. */ gateDigest: string; sideEffects: Array<{ nodeId: string; kind: string; }>; } export interface SavedWorkflowChatSideEffectProblem { nodeId: string; path: string; kind: string; guidance: string; } export interface SavedWorkflowRevisionPayloadV1 { workflowId: string; humanVersion: number; createdAt: string; createdBy: SavedWorkflowOwner; sourceRunId?: string; inputs: Record; contextRefs: SavedWorkflowBuiltinContextRef[]; specTemplate: V3SpecTemplate; /** DAG is execution truth; this flag makes documentation drift explicit. */ specStatus: 'current' | 'stale'; dagTemplate: V3DagTemplate; safety: SavedWorkflowSafety; } /** Fields supplied by a save compiler; identity/version/provenance are allocated by the store. */ export type SavedWorkflowRevisionDraft = Omit; export interface StoredSavedWorkflowRevision { schemaVersion: number; revisionId: string; contentHash: string; payload: unknown; } export interface LoadedSavedWorkflowRevision { revisionId: string; contentHash: string; storedSchemaVersion: number; schemaVersion: typeof SAVED_WORKFLOW_REVISION_SCHEMA_VERSION; payload: SavedWorkflowRevisionPayloadV1; migrated: boolean; } export declare class SavedWorkflowSchemaError extends Error { readonly problems: string[]; constructor(problems: string[]); } export declare function validateSavedWorkflowMetadata(raw: unknown): SavedWorkflowMetadata; export declare function mintSavedWorkflowId(uuid?: string): string; /** Lookup normalization affects discovery only; the original Unicode value is preserved. */ export declare function normalizeSavedWorkflowLookupKey(value: string): string; /** Shared by host-owned compilers before they construct an input definition. */ export declare function isValidSavedWorkflowParamName(name: string): boolean; export declare function validateDagTemplate(raw: unknown): V3DagTemplate; export declare function validateSpecTemplate(raw: unknown): V3SpecTemplate; export declare function collectSavedWorkflowChatSideEffectProblems(dagTemplate: V3DagTemplate): SavedWorkflowChatSideEffectProblem[]; export declare function formatSavedWorkflowChatSideEffectProblems(problems: readonly SavedWorkflowChatSideEffectProblem[]): string[]; /** * Authoring-boundary policy gate. Throw when a to-be-saved DAG template has a * chat-facing side effect in a goal node. This is intentionally NOT part of the * structural deserializer (validateDagTemplate) or the read path * (validateSavedWorkflowRevisionPayload): those are traversed when LOADING an * already-saved revision, and gating them would retroactively brick revisions * that were legal before the lint existed. Callers on the write/compile/publish * side (buildSavedWorkflowRevisionBaseline, validateSavedWorkflowRevisionDraft, * v2→v3 migration) invoke this so a fresh authored definition must be * lint-clean, while old revisions stay loadable/show-able/appendable (and can * be fixed by appending a clean revision). */ export declare function assertNoSavedWorkflowChatSideEffects(dagTemplate: V3DagTemplate): void; export declare function computeSavedWorkflowGateDigest(dagTemplate: V3DagTemplate): string; export declare function computeSavedWorkflowSideEffects(dagTemplate: V3DagTemplate): Array<{ nodeId: string; kind: string; }>; export declare function validateSavedWorkflowRevisionPayload(raw: unknown): SavedWorkflowRevisionPayloadV1; /** * Strict host-owned validation for a revision before the store allocates its * identity/version fields. Unknown identity fields are rejected rather than * allowed to override the store's authority later. */ export declare function validateSavedWorkflowRevisionDraft(raw: unknown): SavedWorkflowRevisionDraft; export declare function computeSavedWorkflowRevisionContentHash(schemaVersion: number, payload: unknown): string; export declare function buildSavedWorkflowRevision(payload: unknown): StoredSavedWorkflowRevision; export declare function migrateSavedWorkflowRevisionPayload(schemaVersion: number, payload: unknown): { schemaVersion: number; payload: unknown; migrated: boolean; }; export declare function loadSavedWorkflowRevision(raw: unknown, expected?: { workflowId?: string; revisionId?: string; }): LoadedSavedWorkflowRevision; //# sourceMappingURL=library-schema.d.ts.map