import type { AuthorizationDecision, AuthorizationRequest, AuthorizationSubject } from './authorization.js'; import type { AuthorityQueryPage, AuthorityQueryRequest } from './http-db.js'; /** Durable collection holding one head record per declared invariant. */ export declare const FELTDB_ARCHITECTURE_INVARIANT_COLLECTION = "_feltdb.ArchitectureInvariant"; /** Durable collection holding the immutable declaration of every version. */ export declare const FELTDB_ARCHITECTURE_INVARIANT_VERSION_COLLECTION = "_feltdb.ArchitectureInvariantVersion"; /** Durable collection holding immutable advisory evaluations. */ export declare const FELTDB_ARCHITECTURE_EVALUATION_COLLECTION = "_feltdb.ArchitectureInvariantEvaluation"; export declare const ARCHITECTURE_INVARIANT_CONTRACT_VERSION = 1; /** Largest page a bounded invariant or evaluation query may request. */ export declare const ARCHITECTURE_INVARIANT_MAX_LIMIT = 1000; /** Page size used when a caller does not request one. */ export declare const ARCHITECTURE_INVARIANT_DEFAULT_LIMIT = 100; /** * A free-form label an application uses to group its own invariants. * * FeltDB does not define a taxonomy of architecture. The declaring application * already has one, and a closed list here would quietly become a competing * one. */ export type ArchitectureInvariantCategory = string; export declare const ARCHITECTURE_INVARIANT_SEVERITIES: readonly ["critical", "high", "medium", "low", "info"]; export type ArchitectureInvariantSeverity = typeof ARCHITECTURE_INVARIANT_SEVERITIES[number]; export declare const ARCHITECTURE_INVARIANT_STATUSES: readonly ["active", "inactive"]; export type ArchitectureInvariantStatus = typeof ARCHITECTURE_INVARIANT_STATUSES[number]; /** * How an invariant can be established. * * Not every invariant is mechanically checkable. Some are decided by a test or * a conformance check, some need evidence interpreted by an advisory * evaluator, and some can only be escalated to a person. All three are * first-class: `human-review` is a complete answer to "how is this verified", * not an admission that the model failed to describe it. */ export declare const ARCHITECTURE_VERIFICATION_METHODS: readonly ["automated-test", "contract-conformance", "source-analysis", "runtime-observation", "benchmark", "jev-advisory", "human-review"]; export type ArchitectureVerificationMethod = typeof ARCHITECTURE_VERIFICATION_METHODS[number]; /** * Advisory results an evaluator may record. * * `UNKNOWN` exists so that missing evidence stays missing evidence. An * evaluator that cannot establish a condition records `UNKNOWN`; it does not * record `DRIFT`, and FeltDB never promotes one to the other. */ export declare const ARCHITECTURE_EVALUATION_RESULTS: readonly ["PASS", "DRIFT", "UNKNOWN"]; export type ArchitectureEvaluationResult = typeof ARCHITECTURE_EVALUATION_RESULTS[number]; export declare const ARCHITECTURE_INVARIANT_CAPABILITIES: { readonly declare: "architecture:invariant.declare"; readonly read: "architecture:invariant.read"; readonly evaluate: "architecture:evaluation.record"; readonly readEvaluation: "architecture:evaluation.read"; }; /** * One way this invariant can be established. * * FeltDB stores it and never interprets it. A different evaluator can read the * same declaration without any change to this model. */ export interface ArchitectureInvariantVerification { method: ArchitectureVerificationMethod; /** Where the evidence comes from, as a `scheme:reference`. */ reference?: string; /** The evaluator this entry was written for, when it was written for one. */ evaluator?: string; /** The condition, in whatever form the named evaluator accepts. */ predicate?: string; notes?: string; parameters?: Record; } /** * A relationship to an authority that owns the referenced material. * * The invariant states what must remain true about that authority's own * declaration. It does not become a second copy of it. */ export interface ArchitectureInvariantAuthorityReference { /** The owning authority, for example `.flow`, `appport`, `authboundry`. */ authority: string; /** What is referenced inside that authority. */ reference: string; /** The relationship that must remain true. */ relationship: string; } /** * Provenance, in the terms FeltDB already uses. * * The actor is an `AuthorizationSubject`, the decision id is the one the * existing authorization boundary issued, and the scope is the tenant and * application the record belongs to. Nothing here is a second provenance * mechanism. */ export interface ArchitectureProvenance { subject: AuthorizationSubject; tenant_id: string; application_id: string; recorded_at: string; /** What produced the write, for example `feltdb.cli`, `attn`, `studio`. */ source: string; /** The decision the authorization boundary issued for this write. */ authorization_decision_id?: string; } /** The meaning-bearing part of an invariant. Changing it creates a version. */ export interface ArchitectureInvariantDeclaration { name: string; description: string; category: ArchitectureInvariantCategory; severity: ArchitectureInvariantSeverity; /** The architectural surface the invariant is declared over. */ scope: string; /** How this invariant can be established. At least one entry is required. */ verification: ArchitectureInvariantVerification[]; references: ArchitectureInvariantAuthorityReference[]; } /** The current state of one declared invariant. */ export interface ArchitectureInvariant extends ArchitectureInvariantDeclaration { /** Stable declared identity, unique within a tenant and application. */ id: string; tenant_id: string; application_id: string; contract_version: typeof ARCHITECTURE_INVARIANT_CONTRACT_VERSION; status: ArchitectureInvariantStatus; version: number; /** Digest of the declaration at `version`. */ declaration_digest: string; created_at: string; created_by: AuthorizationSubject; updated_at: string; updated_by: AuthorizationSubject; deactivated_at?: string; deactivated_by?: AuthorizationSubject; deactivation_reason?: string; provenance: ArchitectureProvenance; } /** * One immutable declaration version. * * A version is never rewritten. This is what lets an application answer what * it believed had to be true when an evaluation happened, rather than only * what it believes today. */ export interface ArchitectureInvariantVersion extends ArchitectureInvariantDeclaration { invariant_id: string; tenant_id: string; application_id: string; contract_version: typeof ARCHITECTURE_INVARIANT_CONTRACT_VERSION; version: number; declaration_digest: string; supersedes?: number; change_reason?: string; declared_at: string; declared_by: AuthorizationSubject; provenance: ArchitectureProvenance; } export interface ArchitectureEvaluationFinding { summary: string; severity?: ArchitectureInvariantSeverity; evidence?: string[]; } export interface ArchitectureEvaluator { /** Evaluator identity, for example `jev`. */ id: string; /** Evaluator version, so an evaluation stays attributable to a build. */ version: string; } /** One advisory evaluation, bound to the exact invariant version evaluated. */ export interface ArchitectureEvaluation { id: string; tenant_id: string; application_id: string; contract_version: typeof ARCHITECTURE_INVARIANT_CONTRACT_VERSION; invariant_id: string; invariant_version: number; /** Digest of the declaration as it stood at `invariant_version`. */ invariant_declaration_digest: string; evaluator: ArchitectureEvaluator; result: ArchitectureEvaluationResult; /** References to evidence the evaluator used, for example `git:abc123`. */ evidence: string[]; explanation: string; findings: ArchitectureEvaluationFinding[]; confidence?: number; evaluated_at: string; recorded_at: string; provenance: ArchitectureProvenance; } export interface ArchitectureInvariantPage { invariants: ArchitectureInvariant[]; nextCursor?: string; exhausted: boolean; } export interface ArchitectureInvariantVersionPage { versions: ArchitectureInvariantVersion[]; nextCursor?: string; exhausted: boolean; } export interface ArchitectureEvaluationPage { evaluations: ArchitectureEvaluation[]; nextCursor?: string; exhausted: boolean; } export interface ArchitectureSnapshotEntry { invariant: ArchitectureInvariant; version: ArchitectureInvariantVersion; latestEvaluation?: ArchitectureEvaluation; } export interface ArchitectureSnapshotPage { entries: ArchitectureSnapshotEntry[]; nextCursor?: string; exhausted: boolean; } /** Durable substrate the service writes through. */ export interface ArchitectureInvariantStore { read(collection: string, recordId: string): Promise; create(collection: string, recordId: string, value: T): Promise; replace(collection: string, recordId: string, value: T): Promise; query(request: AuthorityQueryRequest): Promise>; } /** The part of a FeltDB instance this substrate needs. Satisfied by `StateFirstDB`. */ export interface ArchitectureInvariantDatabase { collection(name: string): { get(id: string | number): Promise; insert(data: Partial, id?: string | number): Promise; update(id: string | number, changes: Partial): Promise; }; query>(request: AuthorityQueryRequest): Promise>; } /** Structurally satisfied by the core `AuthorizationClient`. */ export interface ArchitectureAuthorizationGate { check(request: AuthorizationRequest): Promise; } export interface ArchitectureInvariantScope { tenantId: string; applicationId: string; } export interface ArchitectureInvariantAuthorization { gate: ArchitectureAuthorizationGate; subject: AuthorizationSubject; } export interface ArchitectureInvariantServiceOptions { scope: ArchitectureInvariantScope; /** Who is writing. Recorded as provenance on every mutation. */ actor: AuthorizationSubject; /** What produced the write. Recorded as provenance on every mutation. */ source: string; /** FeltDB's existing authorization boundary. Omitted means no narrowing. */ authorization?: ArchitectureInvariantAuthorization; /** Injectable clock, so evidence ordering is testable. */ now?: () => Date; /** Injectable identity, so evaluation ids are testable. */ newEvaluationId?: () => string; } export interface CreateArchitectureInvariantInput extends Partial { id: string; name: string; description: string; category: ArchitectureInvariantCategory; severity: ArchitectureInvariantSeverity; scope: string; } export interface UpdateArchitectureInvariantInput { name?: string; description?: string; category?: ArchitectureInvariantCategory; severity?: ArchitectureInvariantSeverity; scope?: string; verification?: ArchitectureInvariantVerification[]; references?: ArchitectureInvariantAuthorityReference[]; /** Why the meaning changed. Stored on the new version. */ reason?: string; /** Rejects the write when the stored version has moved on. */ expectedVersion?: number; } export interface DeactivateArchitectureInvariantInput { reason?: string; expectedVersion?: number; } export interface ListArchitectureInvariantsInput { status?: ArchitectureInvariantStatus; category?: ArchitectureInvariantCategory; severity?: ArchitectureInvariantSeverity; scope?: string; limit?: number; cursor?: string; } export interface ListArchitectureInvariantVersionsInput { limit?: number; cursor?: string; } export interface RecordArchitectureEvaluationInput { invariantId: string; invariantVersion: number; evaluator: string; evaluatorVersion?: string; result: ArchitectureEvaluationResult; evidence?: string[]; explanation: string; findings?: ArchitectureEvaluationFinding[]; confidence?: number; evaluatedAt?: string | number | Date; /** Caller-supplied identity, for an idempotent retry of the same evaluation. */ evaluationId?: string; } export interface ListArchitectureEvaluationsInput { invariantId?: string; invariantVersion?: number; evaluator?: string; result?: ArchitectureEvaluationResult; limit?: number; cursor?: string; } /** * A store that can only write one collection. * * `evaluations.record()` runs against this, which is what makes "an evaluation * cannot mutate an invariant" a property of the substrate rather than a rule * the recording path is trusted to follow. */ export declare function restrictWritesTo(store: ArchitectureInvariantStore, collection: string): ArchitectureInvariantStore; /** Adapt a FeltDB instance to the durable substrate this service writes through. */ export declare function createArchitectureInvariantStore(db: ArchitectureInvariantDatabase): ArchitectureInvariantStore; /** * The durable architecture invariant substrate. * * `invariants` declares what must be true. `evaluations` retains what an * advisory evaluator observed about it. Neither side can do the other's job. */ export declare class FeltDBArchitectureInvariantService { readonly scope: ArchitectureInvariantScope; private readonly actor; private readonly source; private readonly authorization?; private readonly clock; private readonly newEvaluationId; private readonly evaluationStore; private readonly store; constructor(store: ArchitectureInvariantStore, options: ArchitectureInvariantServiceOptions); /** Durable record key. Scoping by tenant and application is part of identity. */ private scopedKey; private versionKey; private resourceUri; /** * Ask FeltDB's existing authorization boundary, and fail closed. * * With no gate configured the caller has not asked for narrowing, and this * substrate must not invent an authorization answer FeltDB did not give. */ private authorize; private provenance; private readInvariantRow; /** * Every collection read is a bounded, tenant- and application-scoped query * with an explicit order, so a page is reproducible and a cursor resumes * where the previous page ended instead of rescanning the collection. */ private scopedQuery; private writeVersion; readonly invariants: { /** Declare an invariant. The declaration becomes version 1. */ create: (input: CreateArchitectureInvariantInput) => Promise; /** Read the current declaration. */ get: (invariantId: string) => Promise; /** Read one immutable declaration version. */ version: (invariantId: string, version: number) => Promise; /** Page the declaration history of one invariant, oldest version first. */ versions: (invariantId: string, input?: ListArchitectureInvariantVersionsInput) => Promise; /** Page declared invariants within this tenant and application. */ list: (input?: ListArchitectureInvariantsInput) => Promise; /** * Change what an invariant means. * * A changed declaration becomes a new version; the previous version keeps * its exact words, so evaluations recorded against it stay readable. An * update that changes nothing is a no-op and creates no version. */ update: (invariantId: string, input?: UpdateArchitectureInvariantInput) => Promise; /** * Retire an invariant without rewriting it. * * Deactivation is lifecycle, not meaning: the declaration keeps its * version, and evaluations recorded against it remain readable. */ deactivate: (invariantId: string, input?: DeactivateArchitectureInvariantInput) => Promise; }; readonly evaluations: { /** * Retain one advisory evaluation. * * The evaluation binds to the exact invariant version it names, and to * that version's declaration digest. A conclusive result must cite * evidence; `UNKNOWN` need not, because the absence of evidence is what it * reports. */ record: (input: RecordArchitectureEvaluationInput) => Promise; get: (evaluationId: string) => Promise; /** Page retained evaluations within this tenant and application. */ list: (input?: ListArchitectureEvaluationsInput) => Promise; }; /** * Return the current declaration and its latest evaluation for each invariant. * * The invariant page is the snapshot boundary: history is never expanded and * every evaluation lookup is limited to one record. */ readonly snapshot: (input?: ListArchitectureInvariantsInput) => Promise; } /** Bind the durable architecture invariant substrate to a FeltDB instance. */ export declare function createArchitectureInvariantService(db: ArchitectureInvariantDatabase, options: ArchitectureInvariantServiceOptions): FeltDBArchitectureInvariantService; //# sourceMappingURL=architecture-invariant.d.ts.map