Skip to content

project: scaffold cipherstash-extension + middleware-param-transform shaping artifacts#411

Merged
wmadden merged 10 commits into
mainfrom
cipherstash-extension
May 1, 2026
Merged

project: scaffold cipherstash-extension + middleware-param-transform shaping artifacts#411
wmadden merged 10 commits into
mainfrom
cipherstash-extension

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented May 1, 2026

Two new project shaping documents recording our discussion about the envelope-codec pattern for CipherStash and the middleware seam it depends on.

Projects

projects/middleware-param-transform/spec.md (TML-2359)

Promotes beforeExecute middleware to a mutable param-transformation seam: middleware can rewrite outbound ParamRef.value slots before encode runs, with access to the per-query AbortSignal from TML-2330 / ADR 207's CodecCallContext. Scoped mutator (replace values only — cannot rewrite SQL or projection). General-purpose infrastructure: any extension whose codec is network-backed and bulk-friendly (KMS encryption, signing, audit-stamping, schema-bound JSON validation) can write a plan-walking middleware that batches the work and mutates outbound parameters with the result.

projects/cipherstash-extension/spec.md (TML-2360)

@prisma-next/extension-cipherstash, the first real consumer of TML-2330 + TML-2359. Uses the envelope-codec pattern:

  • Write side: users construct envelopes from plaintext (EncryptedString.from('me@example.com')); the extension's middleware walks ParamRefs in beforeExecute, batches all envelope plaintexts into one bulkEncrypt({ signal }) call, replaces values with ciphertexts. Codec encode is identity by the time it runs.
  • Read side: codec decode constructs an envelope wrapping the ciphertext + the column handle ({ table, column } + KMS metadata) supplied by SqlCodecCallContext.column. Users call await row.email.decrypt() per cell, or use bulk-decrypt utilities (decryptAll, post-buffering) to amortize across many envelopes.

Handle is internal to the extension package — no public TypeScript surface. Stored on the envelope via private field / closure (implementation detail).

Project relationships

TML-2330 / PR #400              TML-2359 / middleware-param-transform
       │                                      │
       └──────────┬───────────────────────────┘
                  ▼
        TML-2360 / cipherstash-extension
        (first real consumer of both seams)
  • TML-2330 / PR TML-2330: add per-query codec call context + AbortSignal #400: must merge first; provides the SqlCodecCallContext.column and per-query AbortSignal plumbing the codec uses at decode time.
  • TML-2359: must merge before the cipherstash extension's middleware lands; provides the ParamRefMutator API. The codec / envelope / bulk-decrypt parts of the extension can land independently.

Status

These are shaping artifactsprojects/<project>/spec.md files, no implementation. Per the project workflow, the next step on each is plan generation (drive-create-plan) once the spec is validated. This PR is for collaboration on the specs themselves.

Both specs flag open questions that need stakeholder input before implementation begins. See the "Open Questions" section at the bottom of each.

Open in Web Open in Cursor 

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (12)
  • projects/cipherstash-integration/plan.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/plan.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/spec.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/specs/envelope-codec-extension.spec.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/specs/middleware-param-transform.spec.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/specs/migration-factories.spec.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/specs/psl-encrypted-string-constructor.spec.md is excluded by !projects/**
  • projects/cipherstash-integration/project-1/specs/raw-sql-ast-node.spec.md is excluded by !projects/**
  • projects/cipherstash-integration/project-2/spec.md is excluded by !projects/**
  • projects/cipherstash-integration/spec.md is excluded by !projects/**
  • projects/cipherstash-integration/sql-raw-factory/plan.md is excluded by !projects/**
  • projects/cipherstash-integration/sql-raw-factory/spec.md is excluded by !projects/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: c2a67c6b-88c4-40e5-aea3-e1d8877f3b8f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cipherstash-extension

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 1, 2026

Open in StackBlitz

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-runtime@411

@prisma-next/family-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-mongo@411

@prisma-next/sql-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-runtime@411

@prisma-next/family-sql

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-sql@411

@prisma-next/extension-arktype-json

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-arktype-json@411

@prisma-next/middleware-telemetry

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/middleware-telemetry@411

@prisma-next/mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo@411

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-paradedb@411

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-pgvector@411

@prisma-next/postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/postgres@411

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-orm-client@411

@prisma-next/sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sqlite@411

@prisma-next/target-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-mongo@411

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-mongo@411

@prisma-next/driver-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-mongo@411

@prisma-next/contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract@411

@prisma-next/utils

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/utils@411

@prisma-next/config

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/config@411

@prisma-next/errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/errors@411

@prisma-next/framework-components

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/framework-components@411

@prisma-next/operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/operations@411

@prisma-next/ts-render

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/ts-render@411

@prisma-next/contract-authoring

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract-authoring@411

@prisma-next/ids

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/ids@411

@prisma-next/psl-parser

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-parser@411

@prisma-next/psl-printer

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-printer@411

@prisma-next/cli

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/cli@411

@prisma-next/emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/emitter@411

@prisma-next/migration-tools

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/migration-tools@411

prisma-next

npm i https://pkg.pr.new/prisma/prisma-next@411

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/vite-plugin-contract-emit@411

@prisma-next/mongo-codec

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-codec@411

@prisma-next/mongo-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract@411

@prisma-next/mongo-value

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-value@411

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-psl@411

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-ts@411

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-emitter@411

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-schema-ir@411

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-ast@411

@prisma-next/mongo-orm

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-orm@411

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-builder@411

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-lowering@411

@prisma-next/mongo-wire

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-wire@411

@prisma-next/sql-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract@411

@prisma-next/sql-errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-errors@411

@prisma-next/sql-operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-operations@411

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-schema-ir@411

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-psl@411

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-ts@411

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-emitter@411

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-lane-query-builder@411

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-relational-core@411

@prisma-next/sql-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-builder@411

@prisma-next/target-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-postgres@411

@prisma-next/target-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-sqlite@411

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-postgres@411

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-sqlite@411

@prisma-next/driver-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-postgres@411

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-sqlite@411

commit: 01b944b

@wmadden wmadden force-pushed the cipherstash-extension branch from 10c95d3 to 01b944b Compare May 1, 2026 16:16
@wmadden wmadden marked this pull request as ready for review May 1, 2026 16:19
cursoragent and others added 10 commits May 1, 2026 18:20
…Execute seam

Records the project shape for promoting beforeExecute middleware to a
mutable param-transformation seam (TML-2359). The middleware contract
grows a ParamRefMutator API (replace ParamRef.value only; cannot
rewrite SQL or projection), and MiddlewareContext carries the same
per-query AbortSignal as TML-2330's CodecCallContext.

The seam is general-purpose infrastructure — any extension whose codec
is network-backed and bulk-friendly (KMS encryption, signing,
audit-stamping, schema-bound JSON validation) can write a
plan-walking beforeExecute middleware that batches the work and
mutates outbound parameters with the result. CipherStash's
bulk-encrypt is the first concrete consumer, not the owner.

Spec captures functional + non-functional requirements, acceptance
criteria across mutation surface / cancellation / backwards
compatibility / family parity / type safety, and a worked-example AC
demonstrating the bulk-encrypt middleware shape. Open questions
flagged around Promise-accepting mutator, Mongo's tree-shaped
ParamRef, mutator reuse across chained middleware, and family
extension of MiddlewareContext.
…nsion

Records the project shape for @prisma-next/extension-cipherstash, the
first real consumer of TML-2330 (codec call context) + TML-2359
(middleware param transform). Uses the envelope-codec pattern:

- Write side: users construct envelopes from plaintext
  (EncryptedString.from('me@example.com')); the extension's
  middleware walks ParamRefs in beforeExecute, batches all envelope
  plaintexts into one bulkEncrypt({ signal }) call, replaces values
  with ciphertexts. Codec encode is identity by the time it runs.
- Read side: codec.decode constructs an envelope wrapping the
  ciphertext + the column handle (table, column, KMS metadata)
  supplied by SqlCodecCallContext.column. Users call
  await row.email.decrypt() per cell, or use bulk-decrypt
  utilities (decryptAll, post-buffering) to amortize across many
  envelopes.

Handle is internal to the extension package — no public TypeScript
surface. Stored on the envelope via private field / closure
(implementation detail).

Spec covers package layout, envelope classes, codec, bulk-encrypt
middleware, bulk-decrypt utility, end-to-end ACs, and documentation
expectations. Project's close-out includes migrating the
envelope-codec pattern doc into a durable docs/ location so future
network-backed bulk-amortizable extensions (Vault, AWS KMS, etc.)
have a canonical reference.

Direct dependencies: TML-2330 / PR #400 (must merge first), TML-2359
/ projects/middleware-param-transform/spec.md (must merge before
this project's middleware lands). The codec / envelope / bulk-decrypt
parts can land independently of TML-2359.
Reorganize both shaping specs around the structure a teammate without
project context would actually want to read:

- TL;DR at top with the decision + what it unblocks (1 paragraph).
- Grounding example showing the new code surface end-to-end before any
  architecture detail.
- Decision as 3 load-bearing declarative bullets; mechanical fallout
  consequences described in 'How it works'.
- Why as narrative motivation in one place (no longer dispersed across
  the FR list).
- How it works section with concrete TypeScript shapes and threading,
  detailed enough that an implementer can start coding.
- What this enables / Non-goals split — load-bearing capabilities
  separated from explicit out-of-scope.
- Acceptance criteria slimmed to focused validation hooks (no longer
  redundant: 'middleware can mutate' + 'codec.encode receives mutated
  value' merged into one observable).
- Alternatives considered at the end, collected from real alternatives
  weighed (microtask-coalescing batcher, bulk-codec trait, AST-rewrite
  middleware, async mutator, lazy field-access decryption, KMS provider
  abstraction, public handle type, etc.) instead of dispersed as
  parenthetical justifications.
- Removed all framework-gaps.md references; framework-gaps is a
  transient audit document, the specs describe their problem
  statements inline and link only to ADRs / TML tickets / external
  standards.
- Removed the three-Description-section sprawl from cipherstash-extension
  (collapsed into a single 'How it works' with subsections).
- Moved the cipherstash-extension 'Close-out' section out of the spec
  (project-execution process belongs in the plan, not the spec).

No semantic changes — same decisions, same scope, same dependencies.
The prose is rebuilt to read end-to-end without prior context, with
the design stated explicitly and requirements named as the
validation surface for that design rather than the source the reader
has to reverse-engineer.
…lock Project 1 scope

Promotes cipherstash-extension and middleware-param-transform from standalone
projects into the cipherstash-integration umbrella, and adds two new task
specs covering the PSL constructor surface and migration factories.

Project 1 scope is locked end-to-end-tested: EncryptedString only (3 argument
shapes, nullable + non-nullable), eq + ilike operators, EQL bundle install via
databaseDependencies.init, hand-authored migration.ts using rawSql({...}) for
EQL search-config installation. Other column types (Number/Date/Boolean/Json),
other operator families (orderAndRange, searchableJson), and planner-driven
per-column DDL are deferred to Project 2.

Key design corrections vs the prior drafts:

- Codec descriptor uses post-#402 RuntimeParameterizedCodecDescriptor<P> with
  arktype-validated params (mirrors pgvector's length plumbing).
- PSL surface is namespaced constructors (cipherstash.EncryptedString(...)),
  not attribute form (@cipherstash.encrypted(...)) — attributes can't couple
  legal arguments to the field's scalar type at the grammar level.
- Migration factories ride on the pre-existing Postgres rawSql({...}) escape
  hatch with operationClass: 'additive', not DataTransformOperation. PR #404
  is therefore an indirect (Project-2-only) dependency, not Project 1.
…h middleware-param-transform cross-refs

Rewrites envelope-codec-extension.spec.md against the post-#402 codec API
and the locked Project 1 scope:

- Codec uses RuntimeParameterizedCodecDescriptor<P> with arktype paramsSchema
  for { equality, freeTextSearch }, registered separately from the codec body
  itself (mirrors pgvector's plumbing for length).
- Constrains the column-type surface to EncryptedString only (3 argument
  shapes, nullable + non-nullable). Removes EncryptedJson, EncryptedNumber,
  and other types from scope — those land in Project 2 alongside their codec
  round-trip / search-operator / migration tests.
- Adds the EQL bundle install via databaseDependencies.init, sourced from
  the first-attempt repo's eql-bundle.ts. Same shape pgvector uses for
  CREATE EXTENSION vector.
- Adds operator lowering for eq and ilike, deferring the canonical SQL
  function names to the first-attempt's operation-templates.ts.
- Native type is eql_v2_encrypted (not text), reflecting EQL's actual
  storage type.
- Acceptance criteria expanded to cover end-to-end live-Postgres+EQL tests
  for round-trip, bulk amortization, nullable handling, and cancellation.

Refreshes middleware-param-transform.spec.md cross-references:

- Path depth bumped (../../ → ../../../) for the new specs/ subdirectory
  location.
- Adds back-reference to the umbrella spec.
- Updates the cipherstash-extension cross-reference to point at the new
  envelope-codec-extension.spec.md path.
- Annotates ADR 207 reference as forthcoming with PR #400.
…herstash, narrow sql-raw-factory to public surface

Add raw-sql-ast-node task spec under cipherstash-integration: defines
RawSqlExpr as a new AnyQueryAst arm, the Postgres lowerer arm, and a
planFromAst envelope helper. Cipherstash owns the AST node so the
migration-factories spec can build DataTransformOperations without
depending on the parallel sql-raw-factory project's user-facing
template-literal factory.

Rewrite migration-factories spec accordingly: factories now produce
DataTransformOperation entries carrying invariantIds (per PR #404)
rather than rawSql({...}) additive ops. Each entry's run() builds
a SqlQueryPlan with a RawSqlExpr ast via the package-internal API,
parameterizing all four arguments to eql_v2.add_search_config so user
table/column inputs flow through ParamRefs rather than text-inlined.

Narrow sql-raw-factory spec to its actual scope: the public raw\`...\`
template-literal factory layered on top of the AST node (RawArg type
union, identifier(...) escape hatch, type-level rejection of bare
values, param() ergonomic re-export). Hard upstream dependency on the
AST node existing — which it will, because cipherstash-integration
ships it. sql-raw-factory now consumes that work rather than owning it.

Update umbrella status table and References to reflect: raw-sql-ast-node
joins as a Project 1 task; sql-raw-factory moves from "Direct, upstream
sequencing" dependency to "Downstream consumer (not a dependency)".
… with high-level plan

Restructure the cipherstash-integration project from a single-spec layout
into a three-component umbrella:
- project-1/: searchable-encryption MVP (the previous umbrella spec
  rescoped as Project 1, plus its 5 task specs moved under specs/)
- project-2/: planner-driven DDL + expanded surface (new stub)
- sql-raw-factory/: public raw\`...\` template-literal factory
  (moved from projects/sql-raw-factory/)

New artifacts at the umbrella level:
- spec.md: scope of the umbrella, why three components, cross-component
  design decisions (RawSqlExpr ownership, DataTransformOperation choice,
  end-to-end-tested-only scope), in-flight framework dependency status
  (PRs #400/#402 merged 2026-05-01; #404/#409 still open).
- plan.md: component-level sequencing. Phase A is Project 1 (critical
  path, gated externally on #404 + #409); phase B is sql-raw-factory and
  Project 2 in parallel afterwards, each with its own gating story
  (sql-raw-factory blocks on Project 1's RawSqlExpr AST node landing;
  Project 2 blocks on Project 1 + TML-2338 + TML-2339).

Project 1's spec is reframed: drop "this is the umbrella" language, add
a header pointing to the new umbrella, repath all relative references
for the new directory depth (3-up from project-1/, 4-up from
project-1/specs/, 3-up from sql-raw-factory/). Resolve the previously-
open question about Project 2's on-disk slug.

No content changes to the per-task specs beyond reference repaths.
…e-slice milestones

project-1/plan.md sequences Project 1 as five end-to-end-demoable
milestones rather than one-milestone-per-task-spec:

- M1: framework SPI (raw-sql-ast-node + middleware-param-transform; no
  user-facing surface yet, but the seams unblock other extensions)
- M2: store-only round-trip (psl + envelope-codec storage path; encrypted
  column type works for storage; no operators yet)
- M3: eq operator + manual addSearchConfig migration (first searchable
  round-trip end-to-end against live EQL)
- M4: ilike + activatePendingSearches + decryptAll (completes Project 1's
  user-facing surface; all UMB ACs green)
- M5: close-out per projects/README.md lifecycle

Records that Project 1 is independent of both open framework PRs:
- #404 (invariant-aware ref routing): migration factories carry
  invariantId fields regardless; the routing benefit is retroactive when
  #404 lands.
- #409 (middleware intercept + contentHash): edits the same
  RuntimeMiddleware types but adds non-overlapping fields; whichever
  lands first, the other rebases mechanically.

Updates the umbrella plan and spec to reflect the new posture: PRs #404
and #409 demoted from "hard gating" to "coordinate-only" / "not a
dependency"; status table marks Project 1's plan as drafted.
…ee milestones

sql-raw-factory/plan.md sequences this component as three small milestones
matching the spec's deliverables:

- M1: raw\`...\` template factory + param() ergonomic re-export, with the
  RawArg type union narrowed to ParamRef + Expression (no identifier()
  yet). Type-level rejection of bare values is the entire SQL-injection
  defense; negative type tests pin AC-TYPE2 / AC-TYPE3.
- M2: identifier(...) escape hatch + Postgres lowerer arm with a curated
  adversarial fuzz fixture (quote / null byte / newline) verifying the
  escape function doesn't break out of the surrounding quotes.
- M3: integration + close-out. End-to-end Postgres execution, middleware
  composition, cipherstash bulk-encrypt composition, then the lifecycle
  close-out per projects/README.md.

Critical-path note: M1 hard-merge-blocks on Project 1's M1 landing
(needs the RawSqlExpr AST node + lowerer arm + planFromAst envelope
helper); M3's AC-COMP3 additionally needs Project 1's M2 (cipherstash
codec + bulk-encrypt middleware). M2 is in-component sequencing.

Resolves three of the spec's six open questions at the plan level
(public entry point: dual-export; drop second call signature: confirmed;
contract acquisition: createRaw factory-of-factories) and tags the other
three to specific milestones.

Updates the umbrella plan's status table and Phase B description to
reflect sql-raw-factory's plan as drafted.
Replace stale references to cancelled per-task tickets (TML-2338, TML-2339,
TML-2359, TML-2360) with the three new component-level umbrella tickets
(TML-2373 = Project 1, TML-2374 = sql-raw-factory, TML-2375 = Project 2).

Where the cancelled tickets described real, still-pending work (the per-column
planTypeOperations input shape and prior-state contract that Project 2 needs),
the work is now described in prose with a parenthetical "was TML-XXXX, cancelled
in Linear redesign" so the historical pointer survives.

References to TML-2330, TML-2229, and TML-2292 are kept — those tickets remain
alive in Linear.

Resolves the umbrella's open question on Linear ticket redesign timing:
component-level tracking only, no per-task or per-milestone sub-issues.
@wmadden wmadden force-pushed the cipherstash-extension branch from 01b944b to cba5dfd Compare May 1, 2026 16:20
@wmadden wmadden merged commit 1d8b709 into main May 1, 2026
5 checks passed
@wmadden wmadden deleted the cipherstash-extension branch May 1, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants