Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

1.5 MiB
Raw Blame History

SCRATCHPAD — Invoice Template JSON AST Renderer Cutover

Context

  • Plan folder: ee/docs/plans/2026-02-12-invoice-template-json-ast-renderer-cutover/
  • Date started: 2026-02-12
  • Status: Draft
  • Supersedes architecture direction in: ee/docs/plans/2026-02-09-invoice-template-designer-preview-workspace/

Key Decisions

  • Treat invoice templates as declarative data (AST), not executable code.
  • Keep future calculation/grouping flexibility via declarative transform specs.
  • Add optional strategyId hooks only through explicit allowlist resolution.
  • Use one shared React renderer for preview and backend PDF generation.
  • Keep migration effort minimal: no custom tenant templates exist that require backfill.

Scope Boundaries

In scope:

  • AST schema + evaluator + renderer cutover.
  • Preview + save/load + PDF pipeline updates.
  • Deletion of compiler and custom executor layers.

Out of scope:

  • Arbitrary per-template code execution.
  • Complex migration tooling for existing tenant custom templates.

Existing Code Paths Reviewed

  • Preview pipeline:
    • packages/billing/src/actions/invoiceTemplatePreview.ts
    • packages/billing/src/actions/invoiceTemplatePreviewCache.ts
  • Designer/editor coupling:
    • packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx
    • packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.tsx
    • packages/billing/src/components/invoice-designer/compiler/guiIr.ts
    • packages/billing/src/components/invoice-designer/compiler/assemblyScriptGenerator.ts
    • packages/billing/src/components/invoice-designer/compiler/diagnostics.ts
  • Runtime + rendering:
    • packages/billing/src/lib/invoice-renderer/wasm-executor.ts
    • packages/billing/src/lib/invoice-renderer/quickjs-executor.ts
    • packages/billing/src/lib/invoice-renderer/host-functions.ts
    • packages/billing/src/lib/invoice-renderer/layout-renderer.ts
  • Compile orchestration:
    • packages/billing/src/lib/invoice-template-compiler/assemblyScriptCompile.ts
  • PDF path:
    • server/src/services/pdf-generation.service.ts
  • Persistence/types:
    • packages/billing/src/models/invoice.ts
    • packages/types/src/interfaces/invoice.interfaces.ts
    • server/src/interfaces/invoice.interfaces.ts

Risks To Watch

  • Parity drift while replacing compile/runtime pipeline.
  • AST transform model underpowered for future grouping/calc edge cases.
  • Strategy hook design becoming an unbounded execution escape hatch.

Notes for Implementation Phase

  • Start with pure declarative transform operations.
  • Introduce strategy hooks only where declarative operations are insufficient.
  • Keep strategy registry narrow and explicit.
  • Preserve tenant-safe data access boundaries.

Verification Commands

  • Plan lint/shape:
    • python3 scripts/validate_plan.py ee/docs/plans/2026-02-12-invoice-template-json-ast-renderer-cutover
  • Spot-check references:
    • rg -n "guiIr|assemblyScriptGenerator|assemblyScriptCompile|wasm-executor|quickjs-executor|host-functions" packages/billing/src server/src

Open Questions Tracking

  1. Final Code tab behavior for GUI templates (AST JSON read-only vs hidden).
  2. Initial strategy hook set for MVP.
  3. MVP expectation for layout verification under AST renderer path.

Progress Log

2026-02-12 — F001 implemented

  • Implemented shared AST type system in packages/types/src/lib/invoice-template-ast.ts.
  • Added explicit versioning root model:
    • INVOICE_TEMPLATE_AST_VERSION = 1
    • InvoiceTemplateAst with kind, version, metadata, styles, bindings, transforms, layout.
  • Added discriminated node model for layout tree:
    • document, section, stack, text, field, image, divider, table, totals.
  • Added style model:
    • token catalog and class declarations via InvoiceTemplateStyleCatalog.
    • node style references via InvoiceTemplateNodeStyleRef.
  • Added binding model:
    • value and collection binding catalogs, binding refs, and value expression union.
  • Added transform model shape:
    • filter, sort, group, aggregate, computed-field, totals-compose.
    • transform base includes optional strategyId as schema surface for later allowlisted hook implementation.
  • Exported new AST type module from packages/types/src/index.ts.

Rationale:

  • @alga-psa/types is the correct shared location for contracts consumed by both app and server paths.
  • Defining versioned AST and explicit discriminated unions up front reduces ambiguity before schema/runtime evaluator implementation.

Commands run:

  • npm -w @alga-psa/types run build (fails with existing TS2209 rootDir/export-map ambiguity in this workspace).
  • npx tsc -p packages/types/tsconfig.json --noEmit (same existing TS2209 issue).
  • npm -w @alga-psa/types test (fails on existing unrelated src/interfaces/barrel.test.ts stray tax.interfaces export).

Gotchas:

  • @alga-psa/types package currently has baseline build/test failures unrelated to AST changes; continue with targeted feature implementation and track failures in commit notes.

2026-02-12 — F002 implemented

  • Added runtime AST schema parser in packages/billing/src/lib/invoice-template-ast/schema.ts.
  • Implemented strict Zod schemas for:
    • AST root (kind, version, metadata, styles, bindings, transforms, layout),
    • recursive layout nodes,
    • expressions, predicates, and transform operation payloads.
  • Added structured validation model:
    • InvoiceTemplateAstValidationError (code, path, message),
    • validateInvoiceTemplateAst(input) returning success/error union,
    • parseInvoiceTemplateAst(input) throwing a consolidated message for invalid payloads.
  • Added targeted validator tests in packages/billing/src/lib/invoice-template-ast/schema.test.ts.

Rationale:

  • Runtime schema validation is required before evaluator/renderer cutover so preview/PDF pipelines can fail fast with actionable diagnostics.
  • Strict object validation prevents accidental schema drift and catches unknown fields early.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts (pass).

2026-02-12 — F003 implemented

  • Extended AST node model with explicit repeatable region support:
    • Added dynamic-table node type in packages/types/src/lib/invoice-template-ast.ts.
    • Added InvoiceTemplateRepeatRegionBinding with required sourceBinding and itemBinding.
  • Updated runtime validator in packages/billing/src/lib/invoice-template-ast/schema.ts:
    • Added dynamic-table schema variant.
    • Enforced required repeat metadata (repeat.sourceBinding, repeat.itemBinding).
  • Added/extended tests in packages/billing/src/lib/invoice-template-ast/schema.test.ts to ensure:
    • missing repeat binding metadata fails with structured path-aware errors,
    • valid dynamic table payload passes.

Rationale:

  • Repeatable line-item regions should be first-class AST semantics, not implicit conventions on generic tables.
  • Explicit repeat metadata is required for deterministic evaluator behavior in upcoming features.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts (pass).

2026-02-12 — F004 implemented

  • Completed declarative transform operation representation in AST:
    • Existing transform union now enforced as strict runtime schema in packages/billing/src/lib/invoice-template-ast/schema.ts.
    • Supported operations: filter, sort, group, aggregate, computed-field, totals-compose.
  • Strengthened runtime payload constraints:
    • transforms.operations must be non-empty.
    • sort.keys, aggregate.aggregations, computed-field.fields, totals-compose.totals must be non-empty.
    • logical predicates require at least one condition.
  • Added transform-shape tests in packages/billing/src/lib/invoice-template-ast/schema.test.ts:
    • invalid empty sort.keys rejected with structured path errors,
    • valid composed filter/sort/group/aggregate/computed payload accepted.

Rationale:

  • This locks in declarative transform expressiveness before evaluator implementation and catches malformed transform configs early.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts (pass).

2026-02-12 — F005 implemented

  • Confirmed/retained strategyId?: string on transform operation base model in:
    • packages/types/src/lib/invoice-template-ast.ts
    • packages/billing/src/lib/invoice-template-ast/schema.ts
  • Added runtime acceptance test in packages/billing/src/lib/invoice-template-ast/schema.test.ts ensuring strategyId is valid on grouped/aggregate transforms.

Rationale:

  • Declares extension points in AST shape now, while deferring actual strategy resolution/execution to allowlisted registry implementation.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts (pass).

2026-02-12 — F006 implemented

  • Added allowlisted strategy registry in packages/billing/src/lib/invoice-template-ast/strategies.ts.
  • Implemented explicit APIs:
    • listAllowlistedInvoiceTemplateStrategyIds()
    • isAllowlistedInvoiceTemplateStrategy(strategyId)
    • resolveInvoiceTemplateStrategy(strategyId)
    • executeInvoiceTemplateStrategy(strategyId, input)
  • Added strict unknown-strategy rejection with typed error:
    • InvoiceTemplateStrategyResolutionError
    • error code: STRATEGY_NOT_ALLOWLISTED.
  • Seeded initial allowlisted strategies for upcoming evaluator usage:
    • custom-group-key
    • custom-aggregate
  • Added unit tests in packages/billing/src/lib/invoice-template-ast/strategies.test.ts for known/unknown strategy behavior.

Rationale:

  • Strategy execution must be explicit and allowlisted to preserve non-arbitrary-code security posture while enabling controlled extensibility.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts (pass).

2026-02-12 — F007 implemented

  • Added shared AST evaluator in packages/billing/src/lib/invoice-template-ast/evaluator.ts.
  • Implemented declarative transform execution over invoice collections:
    • filter via predicate evaluation
    • sort via stable multi-key ordering
    • group with optional strategy hook support
    • aggregate for sum/count/avg/min/max (overall + per-group aggregates)
    • computed-field for derived numeric expressions
    • totals-compose for totals from aggregate refs/computation expressions
  • Evaluator exports:
    • evaluateInvoiceTemplateAst(ast, invoiceData)
    • evaluateAstTransforms(ast, invoiceData) alias
    • typed result with output, groups, aggregates, totals, and resolved bindings.
  • Added evaluator test suite in packages/billing/src/lib/invoice-template-ast/evaluator.test.ts.

Rationale:

  • Central evaluator module is the core abstraction needed to unify preview and PDF behavior around AST data-shaping semantics.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts (pass).

2026-02-12 — F008 implemented

  • Added deterministic output normalization in evaluator (packages/billing/src/lib/invoice-template-ast/evaluator.ts):
    • recursive plain-object key sorting before returning output, groups, aggregates, totals, and bindings.
    • stable sort implementation already used index tie-break to preserve deterministic ordering.
  • Added explicit determinism test in packages/billing/src/lib/invoice-template-ast/evaluator.test.ts:
    • repeated evaluation of identical AST+input yields byte-for-byte identical JSON payload.

Rationale:

  • Deterministic evaluation output is required for reproducible preview/PDF parity checks and reliable caching/verification logic.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/evaluator.test.ts (pass).

2026-02-12 — F009 implemented

  • Upgraded evaluator failure handling to structured error model in packages/billing/src/lib/invoice-template-ast/evaluator.ts.
  • Added InvoiceTemplateEvaluationIssue and enriched InvoiceTemplateEvaluationError with:
    • canonical error code,
    • operationId (where applicable),
    • issue list payload for multi-error contexts.
  • Covered required failure classes:
    • SCHEMA_VALIDATION_FAILED (integrated runtime schema validation before evaluation),
    • MISSING_BINDING (undefined source binding),
    • UNKNOWN_STRATEGY / STRATEGY_EXECUTION_FAILED,
    • INVALID_TRANSFORM_INPUT,
    • INVALID_OPERAND (e.g., unresolved aggregate references).
  • Added evaluator tests asserting explicit codes and structured issue payloads in packages/billing/src/lib/invoice-template-ast/evaluator.test.ts.

Rationale:

  • Preview/PDF pipeline error surfacing needs explicit, machine-readable evaluator errors rather than ad hoc thrown strings.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/evaluator.test.ts (pass).

2026-02-12 — F010 implemented

  • Added shared React renderer module in packages/billing/src/lib/invoice-template-ast/react-renderer.tsx.
  • Implemented renderer component + server-safe static markup helper:
    • InvoiceTemplateAstRenderer
    • renderEvaluatedInvoiceTemplateAst(ast, evaluation) -> { html, css }
  • Supported node rendering for:
    • document, section, stack, text, field, image, divider, table, dynamic-table, totals.
  • Implemented expression/value resolution against evaluator bindings and row scope.
  • Implemented class/token CSS generation from AST style catalog.
  • Added renderer tests in packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx for:
    • static text/field/table/totals rendering,
    • style/class consistency,
    • unsafe content escaping in output HTML.

Rationale:

  • This is the shared rendering surface required for both interactive preview and backend PDF paths.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts (pass).

2026-02-12 — F011 implemented

  • Added server-side HTML document wrapper helper in packages/billing/src/lib/invoice-template-ast/server-render.ts.
  • Implemented renderInvoiceTemplateAstHtmlDocument(ast, evaluation, options) to:
    • call the shared React renderer (renderEvaluatedInvoiceTemplateAst),
    • wrap output in a complete <!doctype html><html><head><body> document,
    • include generated CSS + optional additional CSS,
    • support configurable title/body class with HTML escaping.
  • Added unit test packages/billing/src/lib/invoice-template-ast/server-render.test.ts validating complete wrapper output for headless PDF use.

Rationale:

  • PDF pipeline needs a full HTML document entrypoint, but should reuse the exact same AST React renderer output to maintain parity.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/*.test.ts packages/billing/src/lib/invoice-template-ast/*.test.tsx (pass).

2026-02-12 — F012 implemented

  • Added designer workspace -> AST exporter in:
    • packages/billing/src/components/invoice-designer/ast/workspaceAst.ts
    • with helper exportWorkspaceToInvoiceTemplateAst(workspace) and JSON helper.
  • Export mapping now emits versioned InvoiceTemplateAst directly from visual workspace (no IR step).
  • Updated InvoiceTemplateEditor visual save/export path (packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx):
    • replaced IR/AssemblyScript generation in code-view projection with AST JSON projection,
    • on save with GUI designer enabled, persists canonical templateAst payload directly from workspace export,
    • keeps legacy assemblyScriptSource comment persistence only as temporary compatibility scaffolding.
  • Added exporter tests:
    • packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts.

Rationale:

  • This establishes AST as the designer export artifact and removes compiler-IR coupling from the visual export path.

Commands run:

  • npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts (pass).
  • npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (fails due existing React 19 test harness issue: React.act is not a function from @testing-library/react/react-dom-test-utils in this environment).

2026-02-12 — F013 implemented

  • Extended AST utility module (packages/billing/src/components/invoice-designer/ast/workspaceAst.ts) with import/hydration support:
    • importInvoiceTemplateAstToWorkspace(ast) builds designer workspace snapshot from persisted AST.
  • Updated InvoiceTemplateEditor hydration flow (packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx):
    • prefers templateAst payload hydration when available,
    • falls back to legacy embedded-source/localStorage workspace hydration only if AST hydration is unavailable or fails.
  • Added AST import coverage in packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts.
  • Added editor integration expectation for templateAst hydration in packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (execution blocked by existing act-compat issue in current test harness).

Rationale:

  • Save/reopen flow should hydrate editor state from canonical AST representation as cutover progresses.

Commands run:

  • npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts (pass).
  • npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (editor test files fail due existing React.act is not a function harness issue).

2026-02-12 — F014 implemented

  • Confirmed InvoiceTemplateEditor no longer imports or calls:
    • extractInvoiceDesignerIr
    • generateAssemblyScriptFromIr
  • Save path now uses AST exporter (exportWorkspaceToInvoiceTemplateAst) instead of IR/compiler generation.

Verification:

  • rg -n "extractInvoiceDesignerIr|generateAssemblyScriptFromIr" packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx (no matches).

2026-02-12 — F015 implemented

  • Updated shared and server invoice template contracts to include canonical AST payload:
    • packages/types/src/interfaces/invoice.interfaces.ts
    • server/src/interfaces/invoice.interfaces.ts
  • Contract updates:
    • added templateAst?: InvoiceTemplateAst | null
    • relaxed assemblyScriptSource from required to optional (assemblyScriptSource?: string) for cutover compatibility.
  • Added type contract test:
    • packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts
    • verifies IInvoiceTemplate accepts AST payload without requiring legacy AssemblyScript source.

Commands run:

  • npx vitest run packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts (pass).

2026-02-12 — F016 implemented

  • Added DB migration for tenant template AST persistence:
    • server/migrations/20260212143000_add_template_ast_to_invoice_templates.cjs
    • introduces nullable templateAst JSONB column on invoice_templates.
  • Updated template read/write repository/model paths:
    • packages/billing/src/actions/invoiceTemplates.ts
      • getInvoiceTemplate now selects templateAst,
      • saveInvoiceTemplate now treats templateAst payload as canonical and skips compile gating for AST templates.
    • packages/billing/src/models/invoice.ts
      • tenant template list path includes templateAst,
      • upsert merge list includes templateAst.
  • Updated API schema contract:
    • server/src/lib/api/schemas/invoiceSchemas.ts
    • assemblyScriptSource optional, templateAst optional nullable object payload.
  • Added wiring tests:
    • packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts.

Rationale:

  • Persistence/read paths now treat AST as first-class template payload while keeping legacy fields for transition compatibility.

Commands run:

  • npx vitest run packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (pass).
  • npx vitest run packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts (pass).

2026-02-12 — F017 implemented

  • Added AST-based standard template definitions:
    • packages/billing/src/lib/invoice-template-ast/standardTemplates.ts
    • includes standard-default and standard-detailed canonical AST payloads.
  • Added DB migration for standard template AST persistence:
    • server/migrations/20260212143500_add_template_ast_to_standard_invoice_templates.cjs
  • Updated standard template read/update wiring:
    • packages/billing/src/models/invoice.ts now selects templateAst for standard templates and falls back to AST definitions by standard code.
    • packages/billing/src/actions/invoiceTemplates.ts now writes canonical templateAst during compileStandardTemplate updates.
  • Added tests:
    • packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts
    • extended packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts for standard-template AST wiring assertions.

Rationale:

  • Standard templates now have AST-native source representations, enabling unified renderer/evaluator behavior with tenant templates.

Commands run:

  • npx vitest run packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (pass).

2026-02-12 — F018 implemented

  • Rewrote authoritative preview execution path in packages/billing/src/actions/invoiceTemplatePreview.ts:
    • replaced GUI IR + AssemblyScript compile + Wasm execution path inside runAuthoritativeInvoiceTemplatePreview,
    • now exports workspace to AST (exportWorkspaceToInvoiceTemplateAst), validates schema (validateInvoiceTemplateAst), evaluates transforms (evaluateInvoiceTemplateAst), and renders HTML/CSS via shared React renderer (renderEvaluatedInvoiceTemplateAst).
  • Preview response semantics for this stage:
    • sourceHash now hashes canonical AST JSON,
    • generatedSource now carries AST JSON,
    • compile section is retained for compatibility but no longer performs compilation (cacheHit=false, diagnostics reflect AST/evaluator issues).
  • Updated integration coverage in packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts:
    • now asserts AST validation+evaluator+renderer execution and rendered output presence,
    • invocation adjusted to pass mocked auth/context args because withAuth is mocked as identity in this suite.

Rationale:

  • This completes the preview runtime cutover for authoritative rendering while preserving response shape compatibility for downstream UI wiring.

Commands run:

  • pnpm vitest packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (pass).
  • pnpm vitest packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx (tests pass; run exits non-zero in this environment due pre-existing coverage temp dir server/coverage/.tmp ENOENT after reporting).

2026-02-12 — F019 implemented

  • Preserved Sample/Existing source-selection semantics for preview UX after AST backend cutover.
  • Added source-mode specific test coverage in pure preview state/status modules:
    • packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts
      • sample source validity now explicitly verified to depend on preview sample payload.
    • packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts
      • source toggle flow verifies sample selection is preserved across Sample <-> Existing transitions.

Rationale:

  • These tests guard the source-selection UX contract independently of the compile/runtime pipeline internals.

Commands run:

  • pnpm vitest packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (pass).
  • pnpm vitest packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (test passes; command exits non-zero in this environment due existing coverage temp dir issue: server/coverage/.tmp ENOENT).
  • Attempted targeted DesignerVisualWorkspace component source-switch tests; blocked by pre-existing React.act is not a function compatibility issue in current React/testing-library stack.

2026-02-12 — F020 implemented

  • Remapped preview pipeline phase semantics from compile/render/verify to shape/render/verify in designer preview state and UI surface.
  • Updated preview state model and reducer:
    • packages/billing/src/components/invoice-designer/preview/previewSessionState.ts
    • renamed compileStatus/compileError -> shapeStatus/shapeError
    • phase enum now uses 'shape' | 'render' | 'verify'.
  • Updated phase display derivation:
    • packages/billing/src/components/invoice-designer/preview/previewStatus.ts
    • status snapshot now tracks shapeStatus.
  • Updated DesignerVisualWorkspace status wiring and UX copy:
    • dispatches/reads shape phase state,
    • status label now reads Shape,
    • loading text updated to Shaping and rendering preview...,
    • automation IDs moved from ...preview-compile-* to ...preview-shape-* for status/error/diagnostics/cache markers.
  • Updated related tests:
    • previewSessionState.test.ts
    • previewStatus.test.ts
    • string/automation-id expectations in DesignerVisualWorkspace.test.tsx aligned to shape terminology.

Rationale:

  • Preview UX now reflects the AST pipeline's shaping step instead of a compiler phase.

Commands run:

  • pnpm vitest packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts (pass).

2026-02-12 — F021 implemented

  • Retained and strengthened structured preview diagnostics with AST/evaluator context in runAuthoritativeInvoiceTemplatePreview:
    • packages/billing/src/actions/invoiceTemplatePreview.ts
    • expanded diagnostic payload with kind, code, path, and operationId metadata.
    • schema validation failures now emit kind: 'schema' diagnostics with path/code context.
    • evaluator failures now emit kind: 'evaluation' diagnostics with operation/path/code context.
    • non-evaluator runtime failures now emit kind: 'runtime' diagnostics.
  • Updated preview diagnostics rendering surface:
    • packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.tsx
    • diagnostics list now renders contextual code/path/op metadata alongside message severity.
  • Added integration coverage for structured diagnostics:
    • packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts
    • validates schema diagnostic context mapping and evaluator diagnostic context mapping.

Rationale:

  • Preview diagnostics now preserve machine-meaningful context needed for targeted AST/evaluator debugging without reverting to compiler-era error formats.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts (pass).

2026-02-12 — F022 implemented

  • Updated server PDF generation invoice path to use AST evaluator + shared renderer output instead of Wasm execution in:
    • server/src/services/pdf-generation.service.ts
  • Changes made:
    • removed getCompiledWasm, executeWasmTemplate, and renderLayout usage/imports from invoice PDF rendering flow,
    • now requires canonical templateAst on selected template,
    • evaluates AST with evaluateInvoiceTemplateAst,
    • produces complete HTML document via renderInvoiceTemplateAstHtmlDocument for Puppeteer PDF generation.
  • Added wiring coverage:
    • packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts
    • asserts PDF service uses AST helper path and no longer references Wasm execution helpers.

Rationale:

  • Backend invoice PDF generation now consumes the declarative AST rendering path and removes runtime dependence on Wasm executor in the PDF service.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (pass).

2026-02-12 — F023 implemented

  • Aligned preview and PDF/server render paths onto shared AST evaluator/renderer modules.
  • Updated template server-render action in:
    • packages/billing/src/actions/invoiceTemplates.ts
    • renderTemplateOnServer no longer executes Wasm; it now:
      • resolves template from tenant+standard template set,
      • requires canonical templateAst,
      • evaluates via evaluateInvoiceTemplateAst,
      • renders via renderEvaluatedInvoiceTemplateAst.
  • Extended parity wiring assertions in:
    • packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts
    • verifies preview action, PDF service, and renderTemplateOnServer all use AST evaluator/renderer stack.

Rationale:

  • This ensures preview and both server-side rendering entry points share the same rendering core and reduces parity drift risk.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (pass).

2026-02-12 — F024 implemented

  • Removed preview compile-cache/Wasm artifact cache logic from preview pipeline.
  • Deleted cache module and its unit tests:
    • packages/billing/src/actions/invoiceTemplatePreviewCache.ts (deleted)
    • packages/billing/src/actions/invoiceTemplatePreview.cache.test.ts (deleted)
  • Updated preview action contract and implementation:
    • packages/billing/src/actions/invoiceTemplatePreview.ts
    • removed cache imports and cache key resolution,
    • removed cached artifact lookup/set operations,
    • removed cacheHit fields from preview compile status payload,
    • removed preview input cache-bypass flag from authoritative preview path.
  • Updated preview UI status behavior:
    • packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.tsx
    • removed cache-hit badge and cache-bypass request plumbing while preserving manual rerun behavior.
  • Updated related tests and added explicit cache-removal wiring coverage:
    • packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts
    • packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx
    • packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (new).

Rationale:

  • Preview execution no longer compiles or executes Wasm, so compile-artifact cache lifecycle is obsolete and removed.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts (pass).

2026-02-12 — F025 implemented

  • Deleted PRD-listed legacy compiler/executor modules from billing package:
    • packages/billing/src/components/invoice-designer/compiler/guiIr.ts
    • packages/billing/src/components/invoice-designer/compiler/assemblyScriptGenerator.ts
    • packages/billing/src/components/invoice-designer/compiler/diagnostics.ts
    • packages/billing/src/lib/invoice-template-compiler/assemblyScriptCompile.ts
    • packages/billing/src/lib/invoice-renderer/wasm-executor.ts
    • packages/billing/src/lib/invoice-renderer/quickjs-executor.ts
    • packages/billing/src/lib/invoice-renderer/host-functions.ts
  • Removed associated dead test/snapshot scaffolding tied to deleted modules.
  • Reworked affected action paths to remove imports of deleted modules:
    • packages/billing/src/actions/invoiceTemplatePreview.ts now only contains AST preview runtime path,
    • packages/billing/src/actions/invoiceTemplates.ts no longer imports compiler helper module.
  • Added explicit removal wiring test:
    • packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts.

Rationale:

  • This removes the custom compiler/executor layer from billing runtime code and enforces absence via tests.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (pass).

2026-02-12 — F026 implemented

  • Removed save-time AssemblyScript compile and Wasm persistence behavior from invoice template actions:
    • packages/billing/src/actions/invoiceTemplates.ts
  • saveInvoiceTemplate now persists template metadata directly (AST canonical) without compile gating.
  • compileAndSaveTemplate retained as compatibility API shape but now performs direct metadata save (no compile command, no Wasm generation).
  • compileStandardTemplate now updates assemblyScriptSource/templateAst/sha only and no longer writes compiled wasmBinary artifacts.
  • Updated startup sync behavior accordingly:
    • server/src/lib/startupTasks.ts no longer treats missing wasmBinary as a recompilation trigger.
  • Updated wiring tests to enforce no save-time compile path:
    • packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts
    • packages/billing/src/actions/invoiceTemplateCompileParity.test.ts

Rationale:

  • Template save/update behavior now reflects AST-as-data architecture and avoids compiler lifecycle during persistence.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts (pass).

2026-02-12 — F027 implemented

  • Removed runtime dependency on getCompiledWasm for invoice rendering paths.
  • Active render entry points now use AST evaluator/renderer stack and do not fetch compiled Wasm:
    • packages/billing/src/actions/invoiceTemplates.ts (renderTemplateOnServer)
    • server/src/services/pdf-generation.service.ts
    • packages/billing/src/actions/invoiceTemplatePreview.ts
  • getCompiledWasm action remains only as an explicit unsupported guard path and is not used by rendering flows.
  • Added/updated wiring assertions to prevent regressions:
    • packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts
    • packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts

Rationale:

  • Invoice runtime rendering no longer depends on Wasm artifact retrieval lifecycle.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts (pass).

2026-02-12 — F028 implemented

  • Defined and verified compatibility behavior where legacy template columns may coexist with canonical AST payloads.
  • Runtime rendering paths now explicitly treat templateAst as canonical and do not consume legacy assemblyScriptSource/wasmBinary columns:
    • server/src/services/pdf-generation.service.ts
    • packages/billing/src/actions/invoiceTemplates.ts (renderTemplateOnServer)
  • Extended wiring coverage:
    • packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts
    • new assertion checks render-action block uses template.templateAst and does not depend on legacy runtime columns.

Rationale:

  • Legacy columns remain available as temporary scaffolding, but runtime cutover behavior is AST-first and deterministic.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts (pass).

2026-02-12 — F029 implemented

  • Reinforced no-arbitrary-code security posture at runtime by exercising strategy allowlist enforcement through preview action integration.
  • Added preview integration coverage for non-allowlisted strategy rejection:
    • packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts
    • mocks AST export with an invalid strategyId and asserts structured UNKNOWN_STRATEGY evaluator diagnostics are returned.
  • Existing strategy registry/evaluator guardrails remain in place:
    • allowlist checks in packages/billing/src/lib/invoice-template-ast/strategies.ts
    • evaluator rejection path in packages/billing/src/lib/invoice-template-ast/evaluator.ts.

Rationale:

  • Strategy execution remains constrained to explicit allowlisted functions and rejects arbitrary IDs in runtime paths.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (pass).

2026-02-12 — F030 implemented

  • Expanded evaluator unit coverage for transform semantics and edge behavior in:
    • packages/billing/src/lib/invoice-template-ast/evaluator.test.ts
  • Added coverage for:
    • explicit composition order behavior (filter -> sort -> group -> aggregate),
    • empty-item edge case behavior for grouping/aggregate/totals composition outputs.
  • Existing AST schema + strategy + evaluator unit suites now cover core transform semantics comprehensively.

Rationale:

  • These tests harden deterministic transform semantics and prevent regressions in composition/edge-case handling.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts (pass).

2026-02-12 — F031 implemented

  • Established integration coverage for AST-based preview pipeline in:
    • packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts
    • packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts
  • Covered integration behaviors include:
    • end-to-end preview action success over AST validation -> evaluator -> renderer,
    • schema diagnostic surfacing,
    • evaluator diagnostic surfacing,
    • strategy allowlist rejection surfaced through preview diagnostics,
    • realistic invoice fixture rendering sanity via mapped invoice payload.

Rationale:

  • Preview integration tests now exercise the AST pipeline directly without compiler/Wasm execution dependencies.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (pass).
  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts (pass).

2026-02-12 — F032 implemented

  • Added integration-style coverage for shared AST renderer in server-side invoice render action:
    • packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts
  • Coverage verifies:
    • canonical templateAst payload renders HTML/CSS through renderTemplateOnServer,
    • missing AST payloads fail explicitly, preventing silent legacy runtime fallback.

Rationale:

  • PDF/server rendering path now has executable tests validating AST renderer behavior beyond static wiring assertions.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts (pass).

2026-02-12 — F033 implemented

  • Added preview/PDF parity integration test:
    • packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts
  • Test exercises both render entry points with identical AST + invoice fixture:
    • preview action: runAuthoritativeInvoiceTemplatePreview
    • server render action: renderTemplateOnServer
  • Parity assertions include:
    • exact HTML/CSS equality,
    • totals value parity (Grand Total),
    • grouped section ordering parity (Products before Services).

Rationale:

  • This provides direct automated guardrails against semantic drift between preview and PDF/server render pipelines.

Commands run:

  • pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts (pass).

2026-02-12 — F034 implemented

  • Replaced outdated invoice template architecture documentation with AST cutover documentation:
    • docs/billing/invoice_templates.md
  • Documentation now describes:
    • canonical InvoiceTemplateAst model and runtime modules,
    • shared preview/PDF evaluator+renderer pipeline,
    • allowlisted strategyId extension mechanism,
    • compatibility behavior for legacy columns,
    • explicit deletion/removal notes for compiler/Wasm stack.

Rationale:

  • Prior docs still described AssemblyScript/Wasm execution path and removed modules. Updated docs now align with runtime reality and PRD cutover architecture.

Verification:

  • Manual doc review of docs/billing/invoice_templates.md for AST pipeline and removal notes coverage.

2026-02-12 — T001 implemented

  • Marked minimal valid AST schema acceptance as implemented via schema unit coverage.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::validates a minimal AST document

Verification:

  • \WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})

RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770925966224"

Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > honors public base override [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: 'http://localhost:8085', runnerBase: undefined, publicBase: 'http://localhost:8085' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > supports relative public base for gateway proxy [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: '/runner', publicBase: '/runner' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > uses absolute public base when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/settings', tenantId: undefined, overrideBase: null, runnerBase: 'https://runner.dev/alga', publicBase: 'https://runner.dev/alga' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > appends tenant when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: null, runnerBase: undefined, publicBase: '/runner' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > falls back to /runner when no public base is set [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: undefined, publicBase: '/runner' }

✓ ee/server/src/lib/extensions/tests/assets/url.shared.test.ts (5 tests) 3ms 36 MB heap used ✓ packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx (3 tests) 8ms 41 MB heap used ✓ packages/billing/src/lib/invoice-template-ast/strategies.test.ts (2 tests) 1ms 42 MB heap used ✓ ee/server/src/tests/unit/tenant-creation.test.ts (4 tests) 1ms 43 MB heap used ✓ packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (4 tests) 6ms 68 MB heap used ✓ ee/server/src/tests/unit/routeParams.resolveInstallId.test.ts (3 tests) 0ms 52 MB heap used ee/temporal-workflows/src/activities/tests/email-activities-simple.test.ts (24 tests | 17 failed) 914ms 79 MB heap used × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with default length of 12 0ms → expected Promise{…} to have property 'length' × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with custom length 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate different passwords each time 0ms × Email Activities - Simple Tests > generateTemporaryPassword > should contain at least one character from each category 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should not contain ambiguous characters 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should handle minimum length of 4 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate secure passwords with high entropy 0ms × Email Activities - Simple Tests > MockEmailService > should send emails successfully 101ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should validate email addresses correctly 0ms × Email Activities - Simple Tests > MockEmailService > should track sent emails for testing 102ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should filter emails by recipient 101ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should simulate failures when configured 101ms × Email Activities - Simple Tests > MockEmailService > should handle invalid email addresses 100ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle multiple recipients 100ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should throw error when no valid recipients 101ms × Email Activities - Simple Tests > MockEmailService > should support email service configuration 0ms → expected Promise{…} to be an instance of MockEmailService ✓ Email Activities - Simple Tests > MockEmailService > should return email templates for testing 0ms ✓ Email Activities - Simple Tests > MockEmailService > should return null for unknown templates 0ms × Email Activities - Simple Tests > MockEmailService > should support clearing sent emails 100ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle delay configuration 102ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > Email Service Factory > should create mock service by default 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should create mock service when explicitly requested 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should throw error for unknown providers 0ms → expected [Function] to throw an error × Email Activities - Simple Tests > Email Service Factory > should pass options to mock service 2ms → expected Promise{…} to be an instance of MockEmailService ✓ server/src/test/unit/readAssistantContentFromSse.test.ts (1 test) 2ms 81 MB heap used stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/projects.e2e.test.ts (22 tests | 22 skipped) 24ms 109 MB heap used ↓ Projects API E2E Tests > Authentication > should reject requests without API key ↓ Projects API E2E Tests > Authentication > should reject requests with invalid API key ↓ Projects API E2E Tests > Authentication > should accept requests with valid API key ↓ Projects API E2E Tests > CRUD Operations > should create a project ↓ Projects API E2E Tests > CRUD Operations > should get a project by ID ↓ Projects API E2E Tests > CRUD Operations > should update a project ↓ Projects API E2E Tests > CRUD Operations > should delete a project ↓ Projects API E2E Tests > CRUD Operations > should list projects with pagination ↓ Projects API E2E Tests > Project Search > should search projects by query ↓ Projects API E2E Tests > Project Statistics > should get project statistics ↓ Projects API E2E Tests > Project Tasks and Tickets > should get project tasks ↓ Projects API E2E Tests > Project Tasks and Tickets > should get project tickets ↓ Projects API E2E Tests > Error Handling > should return 404 for non-existent project ↓ Projects API E2E Tests > Error Handling > should return 400 for invalid project data ↓ Projects API E2E Tests > Error Handling > should return 400 for invalid UUID ↓ Projects API E2E Tests > Filtering > should filter projects by status ↓ Projects API E2E Tests > Filtering > should filter projects by type ↓ Projects API E2E Tests > Filtering > should filter projects by client ↓ Projects API E2E Tests > Project Export > should export projects as CSV ↓ Projects API E2E Tests > Project Export > should export projects as JSON ↓ Projects API E2E Tests > Permissions > should enforce read permissions for listing ↓ Projects API E2E Tests > Permissions > should enforce create permissions ✓ server/src/test/unit/billingPlanSelection.test.ts (5 tests | 1 skipped) 1ms 117 MB heap used stdout | packages/client-portal/src/actions/client-portal-actions/client-tickets.responseSource.test.ts > addClientTicketComment response source metadata > T001: stores metadata.responseSource=client_portal when inserting a client comment Usage statistics enabled (user IDs anonymized)

stdout | packages/client-portal/src/actions/client-portal-actions/client-tickets.responseSource.test.ts > addClientTicketComment response source metadata > T001: stores metadata.responseSource=client_portal when inserting a client comment Converted markdown content for client comment: markdown-content

packages/client-portal/src/actions/client-portal-actions/client-tickets.responseSource.test.ts (1 test | 1 failed) 210ms 127 MB heap used × addClientTicketComment response source metadata > T001: stores metadata.responseSource=client_portal when inserting a client comment 210ms → Failed to add comment ✓ server/src/test/unit/docs/contractPurchaseOrderSupport.docs.test.ts (1 test) 1ms 129 MB heap used ✓ server/src/test/unit/workflowsCeStubEntry.unit.test.tsx (1 test) 0ms 131 MB heap used ✓ packages/projects/src/lib/timeEntryContext.test.ts (1 test) 0ms 135 MB heap used ✓ packages/billing/src/components/invoice-designer/state/designerStore.layout.test.ts (5 tests) 3ms 112 MB heap used ✓ packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (2 tests) 0ms 119 MB heap used ✓ sdk/samples/component/invoicing-demo/tests/handler.test.ts (4 tests) 1ms 122 MB heap used ✓ server/src/test/unit/ui/reopenForEdits.test.ts (2 tests) 1ms 123 MB heap used packages/ui/src/context/SchedulingContext.test.tsx (4 tests | 4 failed) 1ms 136 MB heap used × SchedulingContext > returns default callbacks when no provider is present 0ms → document is not defined × SchedulingContext > renders fallback alert element for agent schedule by default 0ms → document is not defined × SchedulingContext > shows a toast when launching time entry without provider 0ms → document is not defined × SchedulingContext > uses provider callbacks when SchedulingCallbackProvider is present 1ms → document is not defined stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Real-world Phase Drag Scenario > should handle dragging phase to before the first phase Moving Phase 3 before Phase 1: new key = Zz

stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should handle multiple insertions at the beginning Keys after multiple insertions at beginning: [ 'Zv', 'Zw', 'Zx', 'Zy', 'Zz', 'a0' ]

stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should generate correct key when placing phase at the end Key for placing after last: a6 (should be > a5)

stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should generate correct key when placing phase between two phases Key for placing between: a1V (should be between a1 and a2)

stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should generate correct key when placing phase at the beginning Key for placing before first: Zz (should be < a0)

✓ server/src/test/unit/project-actions/phaseReordering.test.ts (9 tests) 1ms 138 MB heap used ✓ packages/event-bus/src/index.pending.test.ts (1 test) 18ms 120 MB heap used ✓ sdk/samples/component/scheduler-demo/tests/handler.test.ts (6 tests) 1ms 127 MB heap used ✓ packages/billing/src/components/invoice-designer/state/designerStore.labelText.test.ts (4 tests) 2ms 140 MB heap used server/src/test/unit/timePeriodSuggester.test.ts (10 tests | 10 failed) 10ms 155 MB heap used × TimePeriodSuggester > suggestNewTimePeriod > should suggest monthly periods with no existing periods 0ms → expected undefined to be '2026-02-12' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest monthly periods with existing periods 0ms → expected undefined to be '2025-02-01' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest weekly periods 1ms → expected undefined to be '2026-02-12' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest yearly periods 0ms → expected undefined to be '2026-02-12' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should handle multiple semi-monthly settings together 1ms → expected undefined to be '2025-01-01' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should handle February correctly in leap years 1ms → expected undefined to be '2024-02-01' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should select settings based on period start date, not current date 1ms → expected undefined to be '2025-01-15' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should handle current date before next period start date in semi-monthly periods 0ms → expected undefined to be '2025-01-15' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest next period after existing periods 5ms → expected undefined to be '2025-01-14' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest period starting in the future after current date 0ms → expected undefined to be '2025-06-01' // Object.is equality stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/teams.e2e.test.ts (36 tests | 36 skipped) 2ms 200 MB heap used ↓ Teams API E2E Tests > Authentication > should require API key for all endpoints ↓ Teams API E2E Tests > Authentication > should reject invalid API key ↓ Teams API E2E Tests > CRUD Operations > Create Team (POST /api/v1/teams) > should create a new team ↓ Teams API E2E Tests > CRUD Operations > Create Team (POST /api/v1/teams) > should validate required fields ↓ Teams API E2E Tests > CRUD Operations > Create Team (POST /api/v1/teams) > should validate manager_id is a valid user ↓ Teams API E2E Tests > CRUD Operations > Get Team (GET /api/v1/teams/:id) > should retrieve a team by ID ↓ Teams API E2E Tests > CRUD Operations > Get Team (GET /api/v1/teams/:id) > should return 404 for non-existent team ↓ Teams API E2E Tests > CRUD Operations > Get Team (GET /api/v1/teams/:id) > should not return teams from other tenants ↓ Teams API E2E Tests > CRUD Operations > Update Team (PUT /api/v1/teams/:id) > should update a team ↓ Teams API E2E Tests > CRUD Operations > Update Team (PUT /api/v1/teams/:id) > should return 404 when updating non-existent team ↓ Teams API E2E Tests > CRUD Operations > Update Team (PUT /api/v1/teams/:id) > should validate update data ↓ Teams API E2E Tests > CRUD Operations > Delete Team (DELETE /api/v1/teams/:id) > should delete a team ↓ Teams API E2E Tests > CRUD Operations > Delete Team (DELETE /api/v1/teams/:id) > should return 404 when deleting non-existent team ↓ Teams API E2E Tests > CRUD Operations > Delete Team (DELETE /api/v1/teams/:id) > should handle teams with members ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should list all teams with default pagination ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should support pagination parameters ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should filter by search query ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should sort teams ↓ Teams API E2E Tests > Team Manager Assignment > Assign Team Manager (PUT /api/v1/teams/:id/manager) > should assign manager and automatically add them as team member ↓ Teams API E2E Tests > Team Manager Assignment > Assign Team Manager (PUT /api/v1/teams/:id/manager) > should not duplicate member if manager is already a team member ↓ Teams API E2E Tests > Team Creation with Manager > should automatically add manager as team member when creating team ↓ Teams API E2E Tests > Team Members > Add Team Member (POST /api/v1/teams/:id/members) > should add a member to a team ↓ Teams API E2E Tests > Team Members > Add Team Member (POST /api/v1/teams/:id/members) > should prevent duplicate members ↓ Teams API E2E Tests > Team Members > Add Team Member (POST /api/v1/teams/:id/members) > should validate user exists ↓ Teams API E2E Tests > Team Members > List Team Members (GET /api/v1/teams/:id/members) > should list team members ↓ Teams API E2E Tests > Team Members > Remove Team Member (DELETE /api/v1/teams/:id/members/:userId) > should remove a member from team ↓ Teams API E2E Tests > Team Members > Remove Team Member (DELETE /api/v1/teams/:id/members/:userId) > should return 404 for non-existent member ↓ Teams API E2E Tests > Team Statistics > should get team statistics ↓ Teams API E2E Tests > Error Handling > should handle invalid UUID format ↓ Teams API E2E Tests > Error Handling > should handle invalid query parameters ↓ Teams API E2E Tests > Error Handling > should handle missing required fields on create ↓ Teams API E2E Tests > Permissions > should enforce read permissions for listing ↓ Teams API E2E Tests > Permissions > should enforce create permissions ↓ Teams API E2E Tests > Permissions > should enforce update permissions ↓ Teams API E2E Tests > Permissions > should enforce delete permissions ↓ Teams API E2E Tests > Multi-tenancy > should isolate teams by tenant stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/contractWizard.integration.test.ts (1 test | 1 skipped) 2ms 207 MB heap used ↓ createClientContractFromWizard > creates downstream client records for fixed-fee contracts ✓ server/src/test/unit/workflowBundleCli.unit.test.ts (2 tests) 4ms 244 MB heap used ✓ packages/core/src/lib/logger.test.ts (1 test) 0ms 247 MB heap used stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts (5 tests | 5 skipped) 2ms 251 MB heap used ↓ Contract Purchase Order Support > T001: invoices table includes po_number + client_contract_id ↓ Contract Purchase Order Support > T002: invoice creation snapshots client_contracts.po_number onto invoices.po_number ↓ Contract Purchase Order Support > T003: invoice generation blocks when po_required=true and po_number is missing ↓ Contract Purchase Order Support > T004: PO consumption sums finalized invoices and unconsumes when status changes away from finalized ↓ Contract Purchase Order Support > T005: overage calculation uses invoice total_amount and contract po_amount (authorized total spend) ✓ server/src/test/unit/tenantSettingsActions.experimentalFeatures.test.ts (10 tests) 7ms 216 MB heap used stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/time-entries.e2e.test.ts (40 tests | 38 failed | 2 skipped) 33ms 236 MB heap used × Time Entries API E2E Tests > Authentication > should require API key for all endpoints 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Authentication > should reject invalid API key 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should start a tracking session 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should stop a tracking session 2ms → → Cannot read properties of undefined (reading 'cleanup') ↓ Time Entries API E2E Tests > Approval Workflow > should approve time entries ↓ Time Entries API E2E Tests > Approval Workflow > should reject invalid entry IDs for approval × Time Entries API E2E Tests > Export > should export time entries to CSV 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Export > should export time entries to JSON 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Statistics > should get time entry statistics 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Templates > should list time entry templates 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk create time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk update time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid UUID format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid query parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid date format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce read permissions for listing 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce create permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce update permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce delete permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant 1ms → → Cannot read properties of undefined (reading 'cleanup') ✓ server/src/test/unit/menuConfig.experimentalFeatures.test.ts (1 test) 0ms 143 MB heap used ✓ packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (3 tests) 1ms 145 MB heap used ✓ packages/billing/tests/deleteContractPermissions.test.ts (1 test) 18ms 150 MB heap used ✓ shared/lib/utils/emailFileConversion.test.ts (4 tests) 4ms 156 MB heap used ✓ ee/server/extensions/samples/ui-kit-showcase/test/scaffold.test.ts (8 tests) 1ms 170 MB heap used stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 999 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-2', remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-2', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Shutdown complete

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 100 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return full bucket for new tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should warn if initialized twice [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should initialize with Redis client [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

✓ server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts (17 tests) 4ms 176 MB heap used ✓ packages/clients/src/lib/durationHelpers.test.ts (7 tests) 0ms 179 MB heap used server/src/test/unit/clientContractActions.overlapExclusive.test.ts (3 tests | 3 failed) 1ms 182 MB heap used × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (start == invoiced period end) 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (end exclusive == invoiced period start) 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > rejects true overlaps with an invoiced period 1ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: fetch completed { status: undefined, ok: true, url: '/api/ext-proxy/test-extension-id/tickets' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: posting apiproxy_response (reader) { requestId: 'req-123', targetOrigin: '*' }

ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 2 failed) 198ms 92 MB heap used ✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 55ms ✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 59ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 0ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 84ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

✓ packages/projects/tests/projectInfoDrawer.test.tsx (1 test) 63ms 104 MB heap used ✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 7ms 108 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 8 failed) 81ms 137 MB heap used × EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_6" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_7" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_8" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... ✓ EE Chat (streaming state) > aborts the streaming request when Stop is clicked 40ms × EE Chat (streaming state) > stops updating token display and ends generation state after Stop 6ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × EE Chat (streaming state) > shows a streaming cursor while receiving tokens 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_5" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × EE Chat (streaming state) > removes the streaming cursor when done is received 6ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_6" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × EE Chat (streaming state) > shows the partial response when a network error occurs mid-stream 8ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save  
  <div class="p-6 pt-0 undefined" > <div class="min-h-[200px]" />    
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > Alga    <div class="message-content" > 

 Hi 

     <div class="message-feedback message-feedback--assistant" > <div class="feedback-container" > <div class="thumbs-container" />      <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
    × EE Chat (streaming state) > shows an interruption indicator when the stream ends without done=true 5ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_6" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_7" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × EE Chat (streaming state) > persists the assistant message after streaming completes 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × EE Chat (streaming state) > persists assistant content matching the final streamed tokens 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_4" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 6 failed) 4079ms 149 MB heap used × ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 1012ms → Found multiple elements with the text: AI Assistant

Here are the matching elements:

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 



Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... ✓ ExperimentalFeaturesSettings > defaults AI Assistant toggle to off 10ms × ExperimentalFeaturesSettings > renders experimental features warning banner 1006ms → Found multiple elements with the text: Experimental

Here are the matching elements:

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × ExperimentalFeaturesSettings > calls updateExperimentalFeatures() with current toggle states on save 1011ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... × ExperimentalFeaturesSettings > shows success feedback after saving 1013ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit  
  <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hov... ✓ ExperimentalFeaturesSettings > updates local state when toggled 8ms ✓ ExperimentalFeaturesSettings > loads current settings on mount 4ms × ExperimentalFeaturesSettings > renders list of features with toggles 11ms → expected [ <button …(8)>…(1), …(7) ] to have a length of 2 but got 8 × ExperimentalFeaturesSettings > disables AI Assistant toggle when not allowed 5ms → expected 'true' to be 'false' // Object.is equality packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 48ms 167 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 26ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 2ms 170 MB heap used stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/RightSidebar.streaming.test.tsx (1 test | 1 failed) 1009ms 170 MB heap used × RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 1008ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_6" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_7" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_8" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_a" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save  
 
 <div class="p-6 pt-0 undefined" > <div class="min-h-[200px]" />    
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" >[...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save  
  <div class="p-6 pt-0 undefined" > <div class="min-h-[200px]" />    
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" >[... ✓ packages/billing/src/components/invoice-designer/DesignerShell.constraints.test.tsx (23 tests) 602ms 253 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 50ms 260 MB heap used packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests | 1 failed) 1140ms 237 MB heap used ✓ InvoiceTemplateEditor preview workspace integration > preserves nested visual workspace state when switching Visual -> Code -> Visual 17ms ✓ InvoiceTemplateEditor preview workspace integration > hydrates workspace from source-embedded designer state 6ms ✓ InvoiceTemplateEditor preview workspace integration > hydrates workspace from localStorage fallback when source has no embedded state 11ms ✓ InvoiceTemplateEditor preview workspace integration > hydrates workspace from persisted templateAst payload 7ms ✓ InvoiceTemplateEditor preview workspace integration > keeps save payload behavior while preview sub-tab is active 20ms ✓ InvoiceTemplateEditor preview workspace integration > does not trigger save writes from preview interactions alone 6ms ✓ InvoiceTemplateEditor preview workspace integration > allows preview workspace access for new templates before name validation 10ms ✓ InvoiceTemplateEditor preview workspace integration > keeps Code tab generated/read-only for GUI templates 30ms × InvoiceTemplateEditor preview workspace integration > enables visual designer in local QA via forceInvoiceDesigner=1 when feature flag is off 1010ms → Unable to find an element by: [data-testid="designer-visual-workspace"]

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save  
  <div class="p-6 pt-0 undefined" > <div class="min-h-[200px]" />    
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" >[...

Ignored nodes: comments, script, style <html> <head />  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save  
  <div class="p-6 pt-0 undefined" > <div class="min-h-[200px]" />    
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div [33... ✓ InvoiceTemplateEditor preview workspace integration > keeps production behavior when feature flag is off and no override is set 5ms ✓ InvoiceTemplateEditor preview workspace integration > keeps generated source synchronized with GUI model while switching Visual and Code 18ms ✓ server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests) 107ms 236 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.constraintHighlights.test.tsx (2 tests) 3ms 257 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1578ms 291 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 317ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 620ms ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 287ms 289 MB heap used ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1622ms 380 MB heap used ✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 162ms 398 MB heap used ✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 951ms 392 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 307ms ✓ EmailLogsClient > updates results when recipient search changes 307ms ✓ EmailLogsClient > updates results when ticket filter changes 308ms ✓ server/src/test/unit/QuickAskOverlay.streaming.test.tsx (1 test) 14ms 411 MB heap used ✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 186ms 395 MB heap used

Test Files 558 failed | 43 passed (601) Tests 105 failed | 274 passed | 66 skipped | 1 todo (446) Errors 1 error Start at 14:52:46 Duration 25.74s (transform 2.21s, setup 290ms, collect 2.93s, tests 13.48s, environment 235ms, prepare 52ms) (pass).

2026-02-12 — T001 implemented

  • Marked minimal AST schema acceptance as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts (validates a minimal AST document).

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts (pass).

2026-02-12 — T002 implemented

  • Marked unknown node-type schema rejection with structured diagnostics as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::returns structured validation errors for invalid AST payloads

Verification:

  • \WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})

RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770925992649"

Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest ✓ packages/billing/src/components/invoice-designer/state/designerStore.layoutMode.test.ts (2 tests) 8ms 15 MB heap used ✓ server/src/test/unit/DocumentationService.test.ts (4 tests) 1ms 41 MB heap used ✓ packages/billing/src/lib/invoice-renderer/layout-renderer.test.ts (2 tests) 1ms 60 MB heap used stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/src/lib/invoice-template-ast/strategies.test.ts (2 tests) 1ms 254 MB heap used stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/accounting/externalTaxImport.integration.test.ts (14 tests | 14 skipped) 20ms 260 MB heap used ↓ External Tax Import > importing tax from external accounting system > should update invoice charges with tax amounts from QuickBooks ↓ External Tax Import > importing tax from external accounting system > should change invoice tax_source from pending_external to external ↓ External Tax Import > importing tax from external accounting system > should create audit record in external_tax_imports table ↓ External Tax Import > importing tax from external accounting system > should update invoice total_amount to include imported tax ↓ External Tax Import > tax allocation across charges > should apply per-line tax amounts from external system ↓ External Tax Import > tax allocation across charges > should handle mix of taxable and non-taxable items ↓ External Tax Import > tax allocation across charges > should handle different tax rates across items ↓ External Tax Import > tax allocation across charges > should distribute proportionally when line matching fails ↓ External Tax Import > tax allocation across charges > should match by charge ID even when external lines are returned out of order ↓ External Tax Import > internal tax calculation is skipped for external delegation > should set tax to zero when invoice has pending_external tax source ↓ External Tax Import > automatic tax import after export > should automatically import tax after exporting invoice with tax delegation ↓ External Tax Import > error handling > should fail if invoice is not pending_external ↓ External Tax Import > error handling > should fail if invoice has no external mapping ↓ External Tax Import > error handling > should fail if external system returns error stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/surveyEmailTemplates.integration.test.ts (2 tests | 2 skipped) 1ms 269 MB heap used ↓ Survey email templates > registers system templates for each supported locale ↓ Survey email templates > renders locale-specific content and falls back to English stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (6 tests) 1ms 277 MB heap used stdout | packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts > renderTemplateOnServer AST integration > renders template HTML/CSS from canonical AST payload [Server Action] Successfully rendered template: tpl-1

✓ packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts (2 tests) 5ms 287 MB heap used stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/ticketPermissions.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/extensions/uiHooks.test.ts (2 tests) 0ms 312 MB heap used ✓ ee/server/src/tests/unit/schedulerHostApi.unit.test.ts (72 tests) 9ms 272 MB heap used server/src/lib/extensions/ui/iframeBridge.test.ts (5 tests | 5 failed) 1ms 279 MB heap used × bootstrapIframe (host bridge) > applies sandbox="allow-scripts" by default when none provided 0ms → window is not defined × bootstrapIframe (host bridge) > throws when allowedOrigin mismatches iframe src origin and RUNNER_PUBLIC_BASE is absolute 0ms → window is not defined × bootstrapIframe (host bridge) > sends bootstrap message with envelope version after load 0ms → window is not defined × bootstrapIframe (host bridge) > adjusts iframe height on resize messages with clamping 0ms → window is not defined × bootstrapIframe (host bridge) > validates contentHash format 0ms → window is not defined stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'db_password_server' from configured provider.

server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts (1 test | 1 skipped) 2ms 285 MB heap used ↓ Tax Rate Changes Mid-Billing Period > should apply correct tax rates based on charge dates stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService REST usage > refreshes OAuth tokens when expired Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials

stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService REST usage > retries after 401 by refreshing token once and logs tenant metadata Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials

server/src/test/unit/accounting/xeroClientService.spec.ts (8 tests | 1 failed) 5ms 306 MB heap used ✓ XeroClientService REST usage > POST /Invoices payload matches spec requirements 0ms ✓ XeroClientService REST usage > normalizes validation errors returned from POST /Invoices 0ms ✓ XeroClientService REST usage > handles empty payload array without issuing network request 0ms ✓ XeroClientService REST usage > sets expected headers for authenticated requests 0ms ✓ XeroClientService REST usage > refreshes OAuth tokens when expired 1ms ✓ XeroClientService REST usage > retrieves accounts, items, tax rates, and tracking categories with normalized structures 0ms × XeroClientService REST usage > retries after 401 by refreshing token once and logs tenant metadata 1ms → expected "spy" to be called 1 times, but got 0 times ✓ XeroClientService REST usage > allows re-export after validation error once mappings are corrected 0ms ✓ ee/server/src/tests/unit/tenant-creation.test.ts (4 tests) 0ms 310 MB heap used ✓ server/src/lib/auth/sessionCookies.test.ts (2 tests) 6ms 313 MB heap used ✓ server/src/test/unit/security/managerScopeRegression.test.ts (1 test) 1ms 314 MB heap used ✓ server/src/test/unit/scheduling/bundledTicketsWorkItemPickerBehavior.test.ts (2 tests) 1ms 316 MB heap used stdout | server/src/lib/email/delayedEmailQueue.redisRecovery.test.ts > DelayedEmailQueue Redis recovery > recreates the Redis client after a zRangeByScore timeout [DelayedEmailQueue] Processing loop started { intervalMs: 60000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 60000 }

stdout | server/src/lib/email/delayedEmailQueue.redisRecovery.test.ts > DelayedEmailQueue Redis recovery > recreates the Redis client after a zRangeByScore timeout [DelayedEmailQueue] Shutting down... [DelayedEmailQueue] Shutdown complete

✓ server/src/lib/email/delayedEmailQueue.redisRecovery.test.ts (1 test) 2ms 318 MB heap used ✓ packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts (1 test) 0ms 299 MB heap used server/src/test/integration/billing/invoiceStatusManagement.integration.test.ts (10 tests | 10 skipped) 1ms 100 MB heap used ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to partially_applied when partial credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to paid when full credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should accumulate multiple partial credits and update status accordingly ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to partially_applied when partial payment is recorded ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to paid when full payment is recorded ↓ Invoice Status Management Integration > Combined Payment and Credit Scenarios > should correctly calculate status with both payments and credits ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to partially_applied when partial refund is recorded ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to sent when full refund is recorded ↓ Invoice Status Management Integration > Status Transition Validation > should not allow payment on cancelled invoice ↓ Invoice Status Management Integration > Status Transition Validation > should not allow credit on draft invoice server/src/test/unit/scheduling/actionGuardWiring.test.ts (7 tests | 4 failed) 2ms 103 MB heap used ✓ delegation guard wiring (static) > fetchTimePeriods enforces delegation via assertCanActOnBehalf 0ms ✓ delegation guard wiring (static) > fetchOrCreateTimeSheet enforces delegation via assertCanActOnBehalf 0ms × delegation guard wiring (static) > fetchTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 1ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeSheet[\s\S]*a…/ × delegation guard wiring (static) > fetchTimeEntriesForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeEntriesForTimeS…/ × delegation guard wiring (static) > fetchWorkItemsForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport { Knex } fro…' to match /export const fetchWorkItemsForTimeShe…/ ✓ delegation guard wiring (static) > reopen/reverse approval is blocked when a timesheet contains invoiced entries 0ms × delegation guard wiring (static) > reopen/reverse approval transitions timesheet and entries to CHANGES_REQUESTED 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /reverseTimeSheetApproval[\s\S]*appr…/ server/src/test/unit/scheduling/approvalBehavior.test.ts (2 tests | 2 failed) 1ms 108 MB heap used × timesheet approval behavior (static) > approveTimeSheet enforces delegation and marks timesheet APPROVED 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const approveTimeSheet[\s\S]…/ × timesheet approval behavior (static) > bulkApproveTimeSheets enforces manager scope via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const bulkApproveTimeSheets[\…/ server/src/test/integration/citusTenantFilterEmailProviders.integration.test.ts (2 tests | 2 failed) 2ms 116 MB heap used × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Microsoft webhook route 2ms → expected 'export { GET, POST } from '@alga-psa…' to contain '.where({ id: row.id, tenant: row.tena…' × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Google webhook route 1ms → expected 'export { POST } from '@alga-psa/inte…' to contain '.where({ id: provider.id, tenant: pro…' stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | eslint-plugin-custom-rules/migration-filename.test.js All tests passed!

✓ eslint-plugin-custom-rules/migration-filename.test.js (14 tests) 17ms 144 MB heap used ✓ server/src/test/unit/workflowsEntryTypingGuard.unit.test.ts (2 tests) 1ms 146 MB heap used ✓ packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts (2 tests) 0ms 152 MB heap used stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/scheduling/deleteTimeEntryBehavior.test.ts (1 test) 1ms 151 MB heap used ✓ tools/nx-tests/nxAffected.test.ts (2 tests) 3861ms 154 MB heap used ✓ nx affected > identifies affected projects from a file list 3087ms ✓ nx affected > includes @alga-psa/clients when client code changes 774ms ✓ packages/clients/src/lib/durationHelpers.test.ts (7 tests) 0ms 156 MB heap used ✓ sdk/samples/component/scheduler-demo/tests/handler.test.ts (6 tests) 1ms 159 MB heap used ✓ tools/nx-tests/nxWorkspace.test.ts (3 tests) 16106ms 162 MB heap used ✓ nx workspace > can generate an nx graph html file 15400ms ✓ nx workspace > runs the alga-module generator in dry-run mode 413ms ✓ packages/core/src/lib/events/publisher.test.ts (1 test) 5ms 126 MB heap used ✓ server/src/test/unit/email/emailLoggingFailure.test.ts (1 test) 22ms 126 MB heap used server/src/test/unit/clientFormValidation.test.ts (20 tests | 12 failed) 9ms 130 MB heap used ✓ Client Form Validation > validateClientName > should accept valid client names 1ms × Client Form Validation > validateClientName > should reject invalid client names 0ms → expected null to be 'Client name must contain letters and …' // Object.is equality × Client Form Validation > validateWebsiteUrl > should accept valid URLs 0ms → expected 'Please enter a real business website …' to be null × Client Form Validation > validateWebsiteUrl > should reject invalid URLs 1ms → expected 'Please enter a domain name, not an IP…' to be 'Please enter a valid website URL (e.g…' // Object.is equality × Client Form Validation > validateEmailAddress > should accept valid email addresses 0ms → expected 'Please enter a valid business email a…' to be null × Client Form Validation > validateEmailAddress > should reject invalid email addresses 0ms → expected 'Please enter a valid email address' to be 'Please enter a valid business email a…' // Object.is equality ✓ Client Form Validation > validatePhoneNumber > should accept valid phone numbers 1ms × Client Form Validation > validatePhoneNumber > should reject invalid phone numbers 1ms → expected null to be 'Please enter a valid phone number' // Object.is equality ✓ Client Form Validation > validatePostalCode > should accept valid US ZIP codes 0ms × Client Form Validation > validatePostalCode > should reject invalid US ZIP codes 0ms → expected 'Please enter a valid ZIP code (e.g., …' to be 'Please enter a valid US ZIP code (e.g…' // Object.is equality × Client Form Validation > validatePostalCode > should validate Canadian postal codes 0ms → expected 'Please enter a valid Canadian postal …' to be 'Please enter a valid Canadian postal …' // Object.is equality ✓ Client Form Validation > validateCityName > should accept valid city names 0ms × Client Form Validation > validateCityName > should reject invalid city names 0ms → expected 'City name must contain letters' to be 'City name must be at least 2 characte…' // Object.is equality ✓ Client Form Validation > validateAddress > should accept valid addresses 0ms × Client Form Validation > validateAddress > should reject invalid addresses 0ms → expected 'Address must contain letters' to be 'Address must be at least 5 characters…' // Object.is equality ✓ Client Form Validation > validateContactName > should accept valid contact names 0ms × Client Form Validation > validateContactName > should reject invalid contact names 0ms → expected 'Contact name must contain meaningful …' to be 'Contact name cannot contain emojis' // Object.is equality ✓ Client Form Validation > validateClientForm > should validate a complete form successfully 0ms × Client Form Validation > validateClientForm > should return errors for invalid form data 3ms → the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string ✓ Client Form Validation > validateClientForm > should allow empty optional fields 0ms ✓ server/src/test/unit/validation/timeEntrySchemaAuditFields.test.ts (2 tests) 1ms 131 MB heap used stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/pricingScheduleIntegration.test.ts (10 tests | 10 skipped) 2ms 132 MB heap used ↓ Pricing Schedule Integration Tests > Create and Persist Pricing Schedules > should create a pricing schedule and persist to database ↓ Pricing Schedule Integration Tests > Create and Persist Pricing Schedules > should retrieve active pricing schedule for a billing period ↓ Pricing Schedule Integration Tests > Create and Persist Pricing Schedules > should handle multiple schedules and return the most recent effective schedule ↓ Pricing Schedule Integration Tests > Pricing Schedule Boundaries > should correctly filter schedules across billing period boundaries ↓ Pricing Schedule Integration Tests > Pricing Schedule Boundaries > should treat schedules with null end_date as ongoing ↓ Pricing Schedule Integration Tests > Pricing Schedule Updates and Deletes > should update an existing pricing schedule ↓ Pricing Schedule Integration Tests > Pricing Schedule Updates and Deletes > should delete a pricing schedule ↓ Pricing Schedule Integration Tests > Pricing Schedule Updates and Deletes > should mark a schedule as expired when setting end_date ↓ Pricing Schedule Integration Tests > Pricing Schedule for No Rates > should allow schedules without custom_rate and treat them as null overrides ↓ Pricing Schedule Integration Tests > Pricing Schedule for No Rates > should return no schedule when contract has none defined ee/temporal-workflows/src/activities/tests/portal-domain-reconcile.integration.test.ts (2 tests | 2 failed) 1ms 134 MB heap used × applyPortalDomainResources > routes virtual service traffic to the app once certificate succeeds 0ms → Missing "./admin.js" specifier in "@alga-psa/db" package × applyPortalDomainResources > creates new manifests and prunes legacy virtual services when the domain changes 1ms → Missing "./admin.js" specifier in "@alga-psa/db" package ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1407ms 177 MB heap used ✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 1ms 181 MB heap used ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests) 76ms 190 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' } iframeBridge: posting apiproxy_response { requestId: 'req-123', targetOrigin: '*' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }

ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 3 failed) 142ms 198 MB heap used × Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 60ms → expected "fetch" to be called with arguments: [ StringContaining{…}, …(1) ]

Number of calls: 0

✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 55ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 25ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 2ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? ✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 3ms 202 MB heap used ✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 159ms 228 MB heap used server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests | 2 failed) 111ms 174 MB heap used ✓ TicketEmailNotifications > renders without errors 1ms ✓ TicketEmailNotifications > is collapsed by default and expands on click 12ms ✓ TicketEmailNotifications > shows loading state while fetching 18ms ✓ TicketEmailNotifications > displays timestamp, recipient, subject, and status for each log entry 12ms ✓ TicketEmailNotifications > shows error message for failed notifications 13ms × TicketEmailNotifications > shows maximum 20 entries initially with Load more when more exist 18ms → Found multiple elements with the role "table"

Here are the matching elements:

Ignored nodes: comments, script, style <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-template_contract_name" > <div class="flex space-x-1 items-center" >  Contract Template  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-start_date" > <div class="flex space-x-1 items-center" >  Start Date  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-end_date" > <div class="flex space-x-1 items-center" >  End Date  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-status" > <div class="flex space-x-1 items-center" >  Status  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-contract_id" > <div class="flex space-x-1 items-center" >  Actions  <span class="text-muted-foreground" />     <tbody class="divide-y divide-gray-100" > <tr class=" bg-[rgb(var(--color-border-50))] hover:bg-primary-50 cursor-pointer transition-colors cursor-pointer " > <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-client_name" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > Acme Co    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-template_contract_name" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > —    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-contract_name" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > Draft Alpha    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-start_date" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > —    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-end_date" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > —    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-status" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border bg-green-100 text-green-800" > Active     <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-contract_id" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > <button aria-expanded="false" aria-haspopup="menu" class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group" data-state="closed" type="button" > <span class="sr-only" > Open menu  <svg class="lucide lucide-ellipsis-vertical h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="12" cy="12" r="1" /> <circle cx="12" cy="5" r="1" /> <circle cx="12" cy="19" r="1" />        

Ignored nodes: comments, script, style <table data-automation-id="ticket-email-notifications-table" >    Jan 01, 2026, 7:00 AM   user0@example.com   S0   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user1@example.com   S1   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user2@example.com   S2   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user3@example.com   S3   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user4@example.com   S4   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user5@example.com   S5   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user6@example.com   S6   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user7@example.com   S7   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user8@example.com   S8   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user9@example.com   S9   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user10@example.com   S10   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user11@example.com   S11   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user12@example.com   S12   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user13@example.com   S13   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user14@example.com   S14   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user15@example.com   S15   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user16@example.com   S16   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user17@example.com   S17   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user18@example.com   S18   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user19@example.com   S19   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —    

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search client contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search by client or contract..." type="text" value="" /> 
 
 <div class="flex flex-wrap gap-2" > <button class="justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 inline-flex items-center gap-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white hover:from-blue-700 hover:to-purple-700 group" type="button" > <svg class="lucide lucide-wand-sparkles h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72" /> <path d="m14 7 3 3" /> <path d="M5 6v4" /> <path d="M19 14v4" /> <path d="M10 2v2" /> <path d="M7 8H3" /> <path d="M21 16h-4" /> <path d="M11 3H9" />  Create Contract    <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="client-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  ... × TicketEmailNotifications > Load more fetches additional entries 37ms → Found multiple elements with the role "table"

Here are the matching elements:

Ignored nodes: comments, script, style <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-template_contract_name" > <div class="flex space-x-1 items-center" >  Contract Template  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-start_date" > <div class="flex space-x-1 items-center" >  Start Date  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-end_date" > <div class="flex space-x-1 items-center" >  End Date  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-status" > <div class="flex space-x-1 items-center" >  Status  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="client-contracts-table-header-contract_id" > <div class="flex space-x-1 items-center" >  Actions  <span class="text-muted-foreground" />     <tbody class="divide-y divide-gray-100" > <tr class=" bg-[rgb(var(--color-border-50))] hover:bg-primary-50 cursor-pointer transition-colors cursor-pointer " > <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-client_name" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > Acme Co    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-template_contract_name" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > —    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-contract_name" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > Draft Alpha    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-start_date" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > —    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-end_date" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > —    <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-status" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border bg-green-100 text-green-800" > Active     <td class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top " data-automation-id="client-contracts-table-cell-0-contract_id" > <div class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap" > <div class="min-w-0" > <button aria-expanded="false" aria-haspopup="menu" class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group" data-state="closed" type="button" > <span class="sr-only" > Open menu  <svg class="lucide lucide-ellipsis-vertical h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="12" cy="12" r="1" /> <circle cx="12" cy="5" r="1" /> <circle cx="12" cy="19" r="1" />        

Ignored nodes: comments, script, style <table data-automation-id="ticket-email-notifications-table" >    Jan 01, 2026, 7:00 AM   user0@example.com   S0   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user1@example.com   S1   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user2@example.com   S2   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user3@example.com   S3   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user4@example.com   S4   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user5@example.com   S5   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user6@example.com   S6   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user7@example.com   S7   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user8@example.com   S8   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user9@example.com   S9   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user10@example.com   S10   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user11@example.com   S11   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user12@example.com   S12   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user13@example.com   S13   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user14@example.com   S14   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user15@example.com   S15   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user16@example.com   S16   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user17@example.com   S17   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user18@example.com   S18   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user19@example.com   S19   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user20@example.com   S20   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user21@example.com   S21   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user22@example.com   S22   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user23@example.com   S23   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user24@example.com   S24   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —    

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search client contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search by client or contract..." type="text" value="" /> 
 
 <div class="flex flex-wrap gap-2" > <button class="justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 inline-flex items-center gap-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white hover:from-blue-700 hover:to-purple-700 group" type="button" > <svg class="lucide lucide-wand-sparkles h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72" /> <path d="m14 7 3 3" /> <path d="M5 6v4" /> <path d="M19 14v4" /> <path d="M10 2v2" /> <path d="M7 8H3" /> <path d="M21 16h-4" /> <path d="M11 3H9" />  Create Contract    <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="client-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  ... ✓ packages/billing/src/components/invoice-designer/DesignerShell.constraints.test.tsx (23 tests) 479ms 232 MB heap used stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 47ms 246 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 16ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 949ms 248 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 306ms ✓ EmailLogsClient > updates results when recipient search changes 306ms ✓ EmailLogsClient > updates results when ticket filter changes 306ms ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 223ms 183 MB heap used server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 6 failed) 3060ms 189 MB heap used × ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 1005ms → Found multiple elements with the text: AI Assistant

Here are the matching elements:

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × ExperimentalFeaturesSettings > defaults AI Assistant toggle to off 4ms → expected 'true' to be 'false' // Object.is equality × ExperimentalFeaturesSettings > renders experimental features warning banner 1006ms → Found multiple elements with the text: Experimental

Here are the matching elements:

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="unchecked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save      
 <div ...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice. 
  <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="unchecked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save      
 <div ... ✓ ExperimentalFeaturesSettings > calls updateExperimentalFeatures() with current toggle states on save 12ms × ExperimentalFeaturesSettings > shows success feedback after saving 1006ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice. 
  <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="unchecked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save      
 <div ...

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice. 
  <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="unchecked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save      
 <div ... ✓ ExperimentalFeaturesSettings > updates local state when toggled 7ms ✓ ExperimentalFeaturesSettings > loads current settings on mount 3ms × ExperimentalFeaturesSettings > renders list of features with toggles 10ms → expected [ <button …(8)>…(1), …(11) ] to have a length of 2 but got 12 × ExperimentalFeaturesSettings > disables AI Assistant toggle when not allowed 6ms → expected 'true' to be 'false' // Object.is equality ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.constraintHighlights.test.tsx (2 tests) 3ms 196 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1636ms 236 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 319ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 623ms ✓ server/src/test/unit/RightSidebar.streaming.test.tsx (1 test) 430ms 246 MB heap used ✓ RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 430ms ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 37ms 285 MB heap used ✓ packages/projects/tests/projectInfoDrawer.test.tsx (1 test) 20ms 253 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 9 failed) 45ms 272 MB heap used × EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice. 
  <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > aborts the streaming request when Stop is clicked 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > stops updating token display and ends generation state after Stop 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > shows a streaming cursor while receiving tokens 6ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > removes the streaming cursor when done is received 5ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > shows the partial response when a network error occurs mid-stream 7ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > shows an interruption indicator when the stream ends without done=true 5ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l6" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l7" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > persists the assistant message after streaming completes 5ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... × EE Chat (streaming state) > persists assistant content matching the final streamed tokens 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_ku" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l6" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> <iframe sandbox="allow-scripts, allow-same-origin" src="http://localhost:3000/ext-ui/test-extension-id/hash/index.html" /> 

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" />  <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental  <div class="text-sm [&_p]:leading-relaxed" > Experimental features may change or be removed without notice.   <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > AI Assistant  <div class="text-sm text-gray-600" > Enable AI-powered Quick Ask and Chat sidebar.   <div class="flex items-center gap-2" > <button aria-checked="true" class="switch-root undefined" data-automation-id="experimental-feature-toggle-aiAssistant" data-state="checked" id="experimental-feature-toggle-aiAssistant" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="checked" />    <div class="flex items-start justify-between gap-6 rounded-md border border-gray-200 p-4" > <div class="min-w-0" > <div class="font-medium" > Workflow Automation  <div class="text-sm text-gray-600" > Enable experimental workflow automation features in Automation Hub.   <div class="flex items-center gap-2" > <button aria-checked="false" class="switch-root undefined" data-automation-id="experimental-feature-toggle-workflowAutomation" data-state="unchecked" id="experimental-feature-toggle-workflowAutomation" role="switch" type="button" value="on" > <span class="switch-thumb" data-state="unchecked" />    <div class="flex justify-end pt-2" > <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save      ... ✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 354ms 284 MB heap used ✓ server/src/test/unit/QuickAskOverlay.streaming.test.tsx (1 test) 24ms 304 MB heap used

Test Files 561 failed | 40 passed (601) Tests 62 failed | 311 passed | 37 skipped (410) Start at 14:53:12 Duration 37.95s (transform 1.69s, setup 228ms, collect 1.07s, tests 29.30s, environment 249ms, prepare 53ms) (pass).

2026-02-12 — T002 implemented

  • Marked unknown node-type rejection with actionable schema diagnostics as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::returns structured validation errors for invalid AST payloads

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T003 implemented

  • Marked dynamic-table repeat metadata enforcement as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::requires repeat binding metadata for dynamic-table nodes

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T004 implemented

  • Marked transform payload shape validation across filter/sort/group/aggregate/computed operations as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::enforces transform payload shapes

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T005 implemented

  • Marked optional strategyId acceptance in schema validation as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::accepts optional strategyId on transform operations

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T006 implemented

  • Marked strategy registry allowlist resolution and unknown-ID rejection as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/strategies.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T007 implemented

  • Marked evaluator filter transform semantics as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies filter transforms to invoice items

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T008 implemented

  • Marked deterministic multi-key sort behavior as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies multi-key sort transforms with stable ordering

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T009 implemented

  • Marked grouping transform bucket output behavior as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies grouping and aggregate transforms

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T010 implemented

  • Marked aggregate totals math (sum/count/avg) as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies grouping and aggregate transforms

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T011 implemented

  • Marked computed-field expression and derived totals behavior as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::computes derived fields and totals composition values

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T012 implemented

  • Marked allowlisted strategy hook execution path as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::executes allowlisted strategy hooks

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T013 implemented

  • Added explicit evaluator unit coverage for strategy hook throw behavior.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts (reports explicit strategy execution errors when strategy hooks throw).

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts (pass).

2026-02-12 — T003 implemented

  • Marked repeat-binding metadata requirements for dynamic tables as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::requires repeat binding metadata for dynamic-table nodes

Verification:

  • \WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})

RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770926031206"

Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'db_password_server' from configured provider.

server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts (1 test | 1 skipped) 20ms 43 MB heap used ↓ Tax Rate Changes Mid-Billing Period > should apply correct tax rates based on charge dates ✓ ee/server/src/tests/unit/basic.test.ts (3 tests) 1ms 32 MB heap used ee/extensions/samples/ui-kit-showcase/test/build.test.ts (1 test | 1 failed) 2ms 33 MB heap used × build output > iframe bundle is generated in ui/dist/iframe 2ms → expected false to be true // Object.is equality ✓ packages/scheduling/tests/serverPageSchedulingProvider.test.ts (1 test) 0ms 57 MB heap used ✓ packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (2 tests) 0ms 57 MB heap used ✓ packages/clients/src/schemas/client.schema.test.ts (4 tests) 1ms 60 MB heap used packages/auth/src/lib/rbac.test.ts (3 tests | 3 failed) 4ms 62 MB heap used × rbac permission checks > allows internal users to use MSP permissions only 0ms → promise rejected "Error: [vitest] No "runWithTenant" export… { codeFrame: '…' }" instead of resolving × rbac permission checks > allows client users to use client permissions only 3ms → promise rejected "Error: [vitest] No "runWithTenant" export… { codeFrame: '…' }" instead of resolving × rbac permission checks > returns aggregated permission results 0ms → [vitest] No "runWithTenant" export is defined on the "@alga-psa/db" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

✓ packages/types/src/interfaces/comment.interface.typecheck.test.ts (1 test) 0ms 63 MB heap used stdout | ee/temporal-workflows/src/activities/tests/test-file-check.test.ts > Check if file actually gets created > should show file exists after test File exists: false File path: /var/folders/8g/3xyjqdpd4hx2h39h4qb2lyvm0000gn/T/test-check-gYZTLn/msp/istio-virtualservice.yaml

✓ ee/temporal-workflows/src/activities/tests/test-file-check.test.ts (1 test) 0ms 64 MB heap used stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/appointmentNotifications.integration.test.ts (29 tests | 29 skipped) 2ms 67 MB heap used ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment request received email to client ↓ Appointment Notification System Integration Tests > Email Notifications > should send new appointment request email to MSP staff ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment approved email with correct locale ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment declined email with reason ↓ Appointment Notification System Integration Tests > Email Notifications > should include tenant settings in all emails ↓ Appointment Notification System Integration Tests > Email Notifications > should replace template variables correctly ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notifications for MSP staff on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on approval ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on decline ↓ Appointment Notification System Integration Tests > Internal Notifications > should include correct link in notifications ↓ Appointment Notification System Integration Tests > Internal Notifications > should populate metadata correctly for staff notifications ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct schedule approvers ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct tenant settings ↓ Appointment Notification System Integration Tests > Helper Function Integration > should map contact to client user ID correctly ↓ Appointment Notification System Integration Tests > Helper Function Integration > should return null for non-existent contact ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format dates with correct locale ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format times with correct locale ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should send email notifications in different languages ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should format dates according to locale in notifications ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should default to English when locale is not supported ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should send cancellation notification to client ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should handle cancellation of already cancelled request gracefully ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include actionable metadata in staff notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include appropriate links for client notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should set correct notification types for different events ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should handle missing email addresses gracefully ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should batch notifications to multiple staff members efficiently ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should include all required data fields in notifications ✓ packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (3 tests) 0ms 67 MB heap used ee/temporal-workflows/src/activities/tests/email-activities.temporal.test.ts (11 tests | 10 failed) 4393ms 108 MB heap used × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should generate secure passwords with proper entropy 0ms → expected Promise{…} to have property 'length' × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should handle various password lengths correctly 1ms → expected Promise{…} to have property 'length' ✓ Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should ensure consistent randomness across calls 0ms × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should send welcome email with valid input 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle invalid email addresses gracefully 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle empty email addresses 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should work with minimal required fields 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should generate proper email content structure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should handle template variable substitution 1ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should not throw exceptions on failure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should handle missing required fields gracefully 0ms → Cannot read properties of undefined (reading 'info') ✓ packages/billing/src/lib/invoice-template-ast/schema.test.ts (5 tests) 3ms 116 MB heap used server/src/test/unit/scheduling/actionGuardWiring.test.ts (7 tests | 4 failed) 2ms 119 MB heap used ✓ delegation guard wiring (static) > fetchTimePeriods enforces delegation via assertCanActOnBehalf 0ms ✓ delegation guard wiring (static) > fetchOrCreateTimeSheet enforces delegation via assertCanActOnBehalf 0ms × delegation guard wiring (static) > fetchTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeSheet[\s\S]*a…/ × delegation guard wiring (static) > fetchTimeEntriesForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeEntriesForTimeS…/ × delegation guard wiring (static) > fetchWorkItemsForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport { Knex } fro…' to match /export const fetchWorkItemsForTimeShe…/ ✓ delegation guard wiring (static) > reopen/reverse approval is blocked when a timesheet contains invoiced entries 0ms × delegation guard wiring (static) > reopen/reverse approval transitions timesheet and entries to CHANGES_REQUESTED 1ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /reverseTimeSheetApproval[\s\S]*appr…/ stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.

ee/temporal-workflows/src/test-utils/test-connection.test.ts (3 tests | 1 failed) 122ms 170 MB heap used ✓ Temporal Connection Tests > should connect to temporalio/auto-setup Docker container 9ms ✓ Temporal Connection Tests > should create TestWorkflowEnvironment for unit tests 110ms × Temporal Connection Tests > should verify Docker Postgres connection 3ms → ✓ ee/server/src/tests/unit/invoicingHostApi.unit.test.ts (4 tests) 3ms 172 MB heap used stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > maps tenant snapshot details when provided by the invoice query payload [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-601", "invoice_date": "2026-02-06", "due_date": "2026-02-20", "currency_code": "USD", "client": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "tenantClientInfo": { "client_name": "Northwind MSP", "location_address": "400 SW Main St", "logo_url": "https://cdn.example.com/logo.png" }, "invoice_charges": [], "subtotal": 0, "tax": 0, "total": 0 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-601", "issueDate": "2026-02-06", "dueDate": "2026-02-20", "customer": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "poNumber": null, "tenantClient": { "name": "Northwind MSP", "address": "400 SW Main St", "logoUrl": "https://cdn.example.com/logo.png" }, "items": [], "subtotal": 0, "tax": 0, "total": 0, "taxSource": "internal", "currencyCode": "USD" }

stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > handles nullable/partial values safely [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": null, "invoice_date": null, "due_date": null, "client": { "name": null, "address": null }, "invoice_charges": [ { "item_id": null, "description": null, "quantity": null, "unit_price": null, "total_price": null } ], "subtotal": null, "tax": null, "total": null } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "N/A", "issueDate": "", "dueDate": "", "customer": { "name": "N/A", "address": "N/A" }, "poNumber": null, "tenantClient": null, "items": [ { "id": "", "description": "", "quantity": 0, "unitPrice": 0, "total": 0 } ], "subtotal": 0, "tax": 0, "total": 0, "taxSource": "internal", "currencyCode": "USD" }

stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > keeps canonical minor-unit payloads unchanged [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-2026-0147", "invoice_date": "2026-02-06", "due_date": "2026-02-20", "currency_code": "USD", "client": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "invoice_charges": [ { "item_id": "svc-monitoring", "description": "Managed Endpoint Monitoring", "quantity": 15, "unit_price": 4200, "total_price": 63000 } ], "subtotal": 87000, "tax": 7830, "total": 94830 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-2026-0147", "issueDate": "2026-02-06", "dueDate": "2026-02-20", "customer": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "poNumber": null, "tenantClient": null, "items": [ { "id": "svc-monitoring", "description": "Managed Endpoint Monitoring", "quantity": 15, "unitPrice": 4200, "total": 63000 } ], "subtotal": 87000, "tax": 7830, "total": 94830, "taxSource": "internal", "currencyCode": "USD" }

stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > normalizes legacy existing-invoice major-unit payloads into minor units [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-005", "invoice_date": "2026-01-01", "due_date": "2026-02-16", "currency_code": "USD", "client": { "name": "Emerald City", "address": "1010 Emerald Street" }, "invoice_charges": [ { "item_id": "line-1", "description": "Premium Rabbit Tracking Services", "quantity": 50, "unit_price": 125, "total_price": 6250 }, { "item_id": "line-2", "description": "Monthly Looking Glass Maintenance", "quantity": 1, "unit_price": 1250, "total_price": 1250 } ], "subtotal": 0, "tax": 0, "total": 7500 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-005", "issueDate": "2026-01-01", "dueDate": "2026-02-16", "customer": { "name": "Emerald City", "address": "1010 Emerald Street" }, "poNumber": null, "tenantClient": null, "items": [ { "id": "line-1", "description": "Premium Rabbit Tracking Services", "quantity": 50, "unitPrice": 12500, "total": 625000 }, { "id": "line-2", "description": "Monthly Looking Glass Maintenance", "quantity": 1, "unitPrice": 125000, "total": 125000 } ], "subtotal": 750000, "tax": 0, "total": 750000, "taxSource": "internal", "currencyCode": "USD" }

stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > keeps tenant snapshot null when tenant details are not present [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-602", "invoice_date": "2026-02-06", "due_date": "2026-02-20", "currency_code": "USD", "client": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "invoice_charges": [], "subtotal": 0, "tax": 0, "total": 0 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-602", "issueDate": "2026-02-06", "dueDate": "2026-02-20", "customer": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "poNumber": null, "tenantClient": null, "items": [], "subtotal": 0, "tax": 0, "total": 0, "taxSource": "internal", "currencyCode": "USD" }

stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > maps db invoice payload numeric and string fields into wasm preview model [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-500", "invoice_date": "2026-02-01", "due_date": "2026-02-15", "currency_code": "USD", "po_number": "PO-1", "tax_source": "internal", "client": { "name": "Acme", "address": "123 Main" }, "invoice_charges": [ { "item_id": "item-1", "description": "Managed Service", "quantity": "2", "unit_price": "1000", "total_price": "2000" } ], "subtotal": "2000", "tax": "100", "total": "2100" } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-500", "issueDate": "2026-02-01", "dueDate": "2026-02-15", "customer": { "name": "Acme", "address": "123 Main" }, "poNumber": "PO-1", "tenantClient": null, "items": [ { "id": "item-1", "description": "Managed Service", "quantity": 2, "unitPrice": 1000, "total": 2000 } ], "subtotal": 2000, "tax": 100, "total": 2100, "taxSource": "internal", "currencyCode": "USD" }

✓ packages/billing/src/lib/adapters/invoiceAdapters.test.ts (6 tests) 1ms 152 MB heap used ✓ packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts (3 tests) 1ms 159 MB heap used ✓ server/src/test/unit/migrations/timeEntriesAuditColumns.test.ts (2 tests) 0ms 160 MB heap used stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Retrieved secret 'db_password_server' from configured provider.

↓ ee/server/src/lib/extensions/tests/registry-v2.test.ts (5 tests | 5 skipped) ✓ server/src/test/unit/menuConfig.experimentalFeatures.test.ts (1 test) 0ms 186 MB heap used ✓ server/src/test/unit/workflowRunDialogEventUtils.test.ts (3 tests) 1ms 187 MB heap used ✓ packages/tickets/src/lib/tests/ticketOriginCreatePath.test.ts (5 tests) 2ms 193 MB heap used ✓ packages/auth/src/components/ssoProviderButtonsImport.test.ts (1 test) 0ms 195 MB heap used server/src/test/integration/payments/stripePaymentIntegration.test.ts (21 tests | 21 skipped) 1ms 197 MB heap used ↓ Stripe Payment Integration - Vulnerability Tests > Race Condition in Concurrent Webhook Processing > should correctly update invoice status when processing concurrent webhooks ↓ Stripe Payment Integration - Vulnerability Tests > Race Condition in Concurrent Webhook Processing > should handle duplicate webhook events idempotently ↓ Stripe Payment Integration - Vulnerability Tests > Tenant Isolation Vulnerabilities > should expose tenant isolation gap when webhook contains different tenant_id ↓ Stripe Payment Integration - Vulnerability Tests > Tenant Isolation Vulnerabilities > should prevent cross-tenant payment recording ↓ Stripe Payment Integration - Vulnerability Tests > Missing Amount and Currency Validation > should accept partial payments and update invoice status appropriately ↓ Stripe Payment Integration - Vulnerability Tests > Missing Amount and Currency Validation > should reject payment in different currency than invoice ↓ Stripe Payment Integration - Vulnerability Tests > Missing Refund Handling > should update invoice status when payment is refunded ↓ Stripe Payment Integration - Vulnerability Tests > Missing Refund Handling > should track partial refunds and update invoice balance ↓ Stripe Payment Integration - Vulnerability Tests > Invoice Status Transition Issues > should reject payments for cancelled invoices ↓ Stripe Payment Integration - Vulnerability Tests > Invoice Status Transition Issues > should reject payments for draft invoices ↓ Stripe Payment Integration - Vulnerability Tests > Webhook Error Handling Gaps > should properly report errors for webhooks referencing non-existent invoices ↓ Stripe Payment Integration - Vulnerability Tests > Webhook Error Handling Gaps > should record webhook events for valid invoices ↓ Stripe Payment Integration - Vulnerability Tests > Payment Link Expiration Issues > should expose payment link expiration beyond Stripe limit ↓ Stripe Payment Integration - Vulnerability Tests > Payment Link Expiration Issues > should expose expired payment links remaining in active status ↓ Stripe Payment Integration - Vulnerability Tests > Integer Overflow and Precision Issues > should expose potential precision loss with large payment amounts ↓ Stripe Payment Integration - Vulnerability Tests > Customer Sharing Vulnerability > should expose potential customer sharing across tenants ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Wrong Redirect URLs in Payment Links > should generate correct client portal redirect URLs ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Refund Events Not Parsed Correctly > should parse charge.refunded events with correct amount and currency ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Refund Events Not Parsed Correctly > should process charge.refunded webhook and record refund ↓ Stripe Payment Integration - Vulnerability Tests > BUG: sessionId Parameter Not Used in Verification > should verify the specific session, not just invoice status ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Incorrect Payment Method Recording > should record payment method as "stripe" not "stripe_stripe" ✓ server/src/test/unit/workflowsEntryTypingGuard.unit.test.ts (2 tests) 0ms 201 MB heap used stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > appends tenant when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: null, runnerBase: undefined, publicBase: '/runner' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > supports relative public base for gateway proxy [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: '/runner', publicBase: '/runner' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > uses absolute public base when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/settings', tenantId: undefined, overrideBase: null, runnerBase: 'https://runner.dev/alga', publicBase: 'https://runner.dev/alga' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > honors public base override [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: 'http://localhost:8085', runnerBase: undefined, publicBase: 'http://localhost:8085' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > falls back to /runner when no public base is set [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: undefined, publicBase: '/runner' }

✓ ee/server/src/lib/extensions/tests/assets/url.shared.test.ts (5 tests) 1ms 204 MB heap used shared/workflow/actions/tests/emailWorkflowActions.responseSource.test.ts (6 tests | 5 failed) 15ms 214 MB heap used × createCommentFromEmail response source metadata > T002: persists metadata.responseSource=inbound_email 0ms → trx is not a function × createCommentFromEmail response source metadata > T003: includes normalized provider type when available 0ms → trx is not a function × createCommentFromEmail response source metadata > google inbound flow resolves to inbound_email metadata source (T017) 0ms → trx is not a function × createCommentFromEmail response source metadata > microsoft inbound flow resolves to inbound_email metadata source (T018) 0ms → trx is not a function × createCommentFromEmail response source metadata > imap inbound flow resolves to inbound_email metadata source (T019) 15ms → trx is not a function ✓ createCommentFromEmail response source metadata > T020: keeps comment response-state semantics unchanged (still non-internal) 0ms ✓ tools/nx-tests/nxWorkspace.test.ts (3 tests) 16520ms 216 MB heap used ✓ nx workspace > initializes and lists projects 423ms ✓ nx workspace > can generate an nx graph html file 15535ms ✓ nx workspace > runs the alga-module generator in dry-run mode 560ms stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts (5 tests | 5 skipped) 34ms 109 MB heap used ↓ Internal Notification Preferences (integration) > creates a notification when preferences allow it ↓ Internal Notification Preferences (integration) > does not create a notification when category preference is disabled ↓ Internal Notification Preferences (integration) > allows subtype preference to override disabled category ↓ Internal Notification Preferences (integration) > renders notification using user locale when localized template exists ↓ Internal Notification Preferences (integration) > falls back to English template while preserving user locale when translation is missing ↓ server/src/test/integration/inboundEmailInApp.webhooks.integration.test.ts (11 tests | 11 skipped) stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Shutdown > should cleanup on shutdown [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Shutdown > should cleanup on shutdown [DelayedEmailQueue] Shutting down... [DelayedEmailQueue] Shutdown complete

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should not process emails that are not ready yet [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Found ready emails { count: 5 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing queued email { id: 't1-email-1', tenantId: 'tenant-1', to: 'user1@tenant1.com', retryCount: 1 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing queued email { id: 't2-email-1', tenantId: 'tenant-2', to: 'user1@tenant2.com', retryCount: 1 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing cycle complete { processedCount: 2, durationMs: 0 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Found ready emails { count: 1 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Processing queued email { id: 'test-id-1', tenantId: 'tenant-1', to: 'test@example.com', retryCount: 1 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Processing cycle complete { processedCount: 1, durationMs: 0 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Stats > should return zero when queue is empty [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Stats > should return pending count [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Found ready emails { count: 1 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Processing queued email { id: 'test-id-1', tenantId: 'tenant-1', to: 'test@example.com', retryCount: 3 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Processing cycle complete { processedCount: 1, durationMs: 1 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Enqueue > should enqueue email with correct delay [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Enqueue > should enqueue email with correct delay [DelayedEmailQueue] Email enqueued for retry { id: '1770926054867-gxjbfn9vg', tenantId: 'tenant-1', to: 'test@example.com', retryCount: 0, readyAt: '2026-02-12T19:55:19.349Z', delayMs: 64482 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Initialization > should warn if initialized twice [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }

stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Initialization > should initialize with Redis client and callback [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }

✓ server/src/test/unit/notifications/delayedEmailQueue.test.ts (18 tests) 3ms 111 MB heap used stdout | sdk/samples/component/secrets-demo/tests/handler.test.ts > handler > echoes secrets and config [mock logging] [secrets-demo] request start tenant=tenant-123 requestId=req-1 method=GET url=/demo configKeys=1 secrets=1 build=2025-11-11T17:34:00Z

stdout | sdk/samples/component/secrets-demo/tests/handler.test.ts > handler > echoes secrets and config [mock logging] [secrets-demo] greeting secret resolved; emitting response

stdout | sdk/samples/component/secrets-demo/tests/handler.test.ts > handler > echoes secrets and config [mock logging] [secrets-demo] request complete requestId=req-1 status=200 build=2025-11-11T17:34:00Z

✓ sdk/samples/component/secrets-demo/tests/handler.test.ts (1 test) 0ms 113 MB heap used stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/imports/importWorkflow.integration.test.ts (3 tests | 3 skipped) 2ms 132 MB heap used ↓ Asset import integration > registers default CSV/RMM importers in the database ↓ Asset import integration > generates preview summaries with validation and duplicate detection for N-able exports ↓ Asset import integration > detects duplicates via MAC normalization and fuzzy hostname matches ✓ ee/server/extensions/samples/ui-kit-showcase/test/scaffold.test.ts (8 tests) 1ms 134 MB heap used stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Initializing event bus [EventBus] Creating new Redis client [RedisConfig] Using configuration: { url: 'redis://localhost:6379', prefix: 'alga-psa:', eventBus: { streamPrefix: 'event-stream:', consumerGroup: 'event-processors', maxStreamLength: 1000, blockingTimeout: 5000, claimTimeout: 30000, batchSize: 10, reconnectStrategy: { retries: 10, initialDelay: 100, maxDelay: 3000 } } } Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout CompositeSecretProvider found app secret 'redis_password' from provider 1

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout Retrieved secret 'redis_password' from configured provider.

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Redis Client Connected [EventBus] Redis Client Ready

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_CREATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_UPDATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_CLOSED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_DELETED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_ASSIGNED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_ADDITIONAL_AGENT_ASSIGNED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_COMMENT_ADDED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_COMMENT_UPDATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_RESPONSE_STATE_CHANGED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_STATUS_CHANGED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_PRIORITY_CHANGED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_UNASSIGNED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_REOPENED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_ESCALATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_QUEUE_CHANGED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_MESSAGE_ADDED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_CUSTOMER_REPLIED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_INTERNAL_NOTE_ADDED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_SLA_STAGE_ENTERED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_SLA_STAGE_MET

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_SLA_STAGE_BREACHED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_CREATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_UPDATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_CLOSED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_ASSIGNED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_TASK_ASSIGNED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_TASK_ADDITIONAL_AGENT_ASSIGNED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TASK_COMMENT_ADDED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TASK_COMMENT_UPDATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TIME_ENTRY_SUBMITTED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TIME_ENTRY_APPROVED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:INVOICE_GENERATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:INVOICE_FINALIZED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CUSTOM_EVENT

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:INBOUND_EMAIL_RECEIVED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:ACCOUNTING_EXPORT_COMPLETED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:ACCOUNTING_EXPORT_FAILED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:SCHEDULE_ENTRY_CREATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:SCHEDULE_ENTRY_UPDATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:SCHEDULE_ENTRY_DELETED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_SYNC_STARTED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_SYNC_COMPLETED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_SYNC_FAILED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_CONFLICT_DETECTED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:MESSAGE_SENT

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:USER_MENTIONED_IN_DOCUMENT

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_CREATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_APPROVED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_DECLINED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_CANCELLED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_CREATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_UPDATED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_DELETED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_ONLINE

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_OFFLINE

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_ALERT_TRIGGERED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_ALERT_RESOLVED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_SYNC_STARTED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_SYNC_COMPLETED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_SYNC_FAILED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_WEBHOOK_RECEIVED

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] No active subscriptions, waiting for handlers to be registered

stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Added handler: { eventType: 'TICKET_CREATED', channel: 'global', handlerName: '', handlersCount: 1 }

packages/event-bus/src/index.hardTimeout.test.ts (1 test | 1 failed) 34ms 209 MB heap used × EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout 34ms → expected 1 to be greater than or equal to 2 ✔ T001: fails with clear error when --test is missing (51.485041ms) ✔ T002: fails with clear error when bundle.json is missing (48.800541ms) ✔ T003: fails with clear error when test.cjs is missing (46.599083ms) stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/tickets.e2e.test.ts (47 tests | 47 skipped) 2ms 275 MB heap used ↓ Ticket API E2E Tests > Authentication > should require API key for all endpoints ↓ Ticket API E2E Tests > Authentication > should reject invalid API key ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create a new ticket ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should validate required fields ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create ticket with all optional fields ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should retrieve a ticket by ID ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should return 404 for non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should not return tickets from other tenants ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should update a ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should return 404 when updating non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should validate update data ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should delete a ticket ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should return 404 when deleting non-existent ticket ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should list all tickets with default pagination ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should support pagination parameters ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by client_id ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by status ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by priority ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by assigned user ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter overdue tickets ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should sort tickets by created date ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search tickets by query ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search in specified fields ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should limit search results ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add a comment to a ticket ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add an internal comment ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should list ticket comments ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should return 404 when adding comment to non-existent ticket ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should update ticket status ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should validate status transitions ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should assign ticket to user ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should unassign ticket ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should return ticket statistics ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by date range ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by client ↓ Ticket API E2E Tests > Create Ticket from Asset (POST /api/v1/tickets/from-asset) > should create ticket from asset ↓ Ticket API E2E Tests > Error Handling > should handle invalid UUID format ↓ Ticket API E2E Tests > Error Handling > should handle invalid query parameters ↓ Ticket API E2E Tests > Error Handling > should handle missing required fields on create ↓ Ticket API E2E Tests > Error Handling > should handle invalid date formats ↓ Ticket API E2E Tests > Permissions > should enforce read permissions for GET endpoints ↓ Ticket API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE ↓ Ticket API E2E Tests > Permissions > should enforce assignment permissions ↓ Ticket API E2E Tests > Multi-tenancy > should isolate tickets by tenant ↓ Ticket API E2E Tests > Advanced Features > should support bulk operations ↓ Ticket API E2E Tests > Advanced Features > should support ticket templates ↓ Ticket API E2E Tests > Advanced Features > should track ticket history stdout | server/src/test/unit/ticketPermissions.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":"PO-XYZ"} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""},{"type": "Text", "content": "PO #: PO-XYZ", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}

stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":null} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}

✓ server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts (1 test) 1436ms 293 MB heap used ✓ server/src/test/unit/email/replyTokenExtraction.test.ts (10 tests) 3ms 263 MB heap used ee/temporal-workflows/src/activities/tests/email-activities-standalone.test.ts (8 tests | 5 failed) 3ms 268 MB heap used × Email Activities - Standalone Tests > Password Generation > should generate secure passwords with default length 0ms → expected Promise{…} to have property 'length' × Email Activities - Standalone Tests > Password Generation > should generate passwords with custom length 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Standalone Tests > Password Generation > should generate unique passwords 0ms × Email Activities - Standalone Tests > Email Activity > should send welcome email successfully 0ms → expected false to be true // Object.is equality × Email Activities - Standalone Tests > Email Activity > should handle invalid email gracefully 1ms → expected 'Tenant ID must be a UUID with 32 hex …' to contain 'Invalid email address' × Email Activities - Standalone Tests > Email Activity > should work with minimal required fields 0ms → expected false to be true // Object.is equality ✓ Email Activities - Standalone Tests > Mock Email Service Integration > should validate email service templates 0ms ✓ Email Activities - Standalone Tests > Mock Email Service Integration > should handle unknown templates 0ms ✓ packages/tickets/src/lib/timeEntryContext.test.ts (3 tests) 0ms 223 MB heap used stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/core/src/lib/events/publisher.test.ts (1 test) 3ms 266 MB heap used stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/services/chatCompletionsService.streaming.test.ts (1 test) 96ms 278 MB heap used ✓ server/src/test/unit/internal-notifications/mentionParser.test.ts (28 tests) 2ms 283 MB heap used server/src/test/integration/internal-notifications/mentionNotifications.integration.test.ts (2 tests | 2 skipped) 19ms 286 MB heap used ↓ Mention notifications via TICKET_COMMENT_ADDED > creates notifications for mentioned users and excludes the author ↓ Mention notifications via TICKET_COMMENT_ADDED > does not notify client portal contact for internal comments ✓ server/src/test/unit/services/numberingService.test.ts (5 tests) 2ms 290 MB heap used ✓ ee/extensions/samples/ui-kit-showcase/test/scaffold.test.ts (8 tests) 1ms 293 MB heap used packages/ui/src/context/SchedulingContext.test.tsx (4 tests | 4 failed) 1ms 297 MB heap used × SchedulingContext > returns default callbacks when no provider is present 0ms → document is not defined × SchedulingContext > renders fallback alert element for agent schedule by default 0ms → document is not defined × SchedulingContext > shows a toast when launching time entry without provider 1ms → document is not defined × SchedulingContext > uses provider callbacks when SchedulingCallbackProvider is present 0ms → document is not defined stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts (2 tests | 2 skipped) 2ms 243 MB heap used ↓ BaseEmailService → email_sending_logs > successful send creates log entry with status sent ↓ BaseEmailService → email_sending_logs > failed send creates log entry with status failed and error_message server/src/test/integration/billing/invoiceStatusManagement.integration.test.ts (10 tests | 10 skipped) 1ms 246 MB heap used ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to partially_applied when partial credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to paid when full credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should accumulate multiple partial credits and update status accordingly ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to partially_applied when partial payment is recorded ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to paid when full payment is recorded ↓ Invoice Status Management Integration > Combined Payment and Credit Scenarios > should correctly calculate status with both payments and credits ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to partially_applied when partial refund is recorded ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to sent when full refund is recorded ↓ Invoice Status Management Integration > Status Transition Validation > should not allow payment on cancelled invoice ↓ Invoice Status Management Integration > Status Transition Validation > should not allow credit on draft invoice stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/contacts.e2e.test.ts (29 tests | 29 failed) 22ms 259 MB heap used × Contact API E2E Tests > Authentication > should require API key for all endpoints 1ms → × Contact API E2E Tests > Authentication > should reject invalid API key 1ms → × Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact 1ms → × Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields 1ms → × Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format 1ms → × Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID 1ms → × Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact 1ms → × Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants 1ms → × Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact 1ms → × Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact 1ms → × Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact 1ms → × Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name 1ms → × Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query 1ms → × Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields 1ms → × Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results 1ms → × Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV 1ms → × Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON 1ms → × Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default 1ms → × Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics 1ms → × Contact API E2E Tests > Error Handling > should handle invalid query parameters 1ms → × Contact API E2E Tests > Error Handling > should handle database errors gracefully 1ms → × Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints 1ms → × Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE 1ms → × Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant 1ms → ↓ server/src/test/integration/inboundEmailInApp.featureFlag.integration.test.ts (1 test | 1 skipped) server/src/lib/eventBus/index.hardTimeout.test.ts (1 test | 1 failed) 4ms 266 MB heap used × EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout 4ms → Failed to resolve entry for package "@alga-psa/event-schemas". The package may have incorrect main/module/exports specified in its package.json. stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts (6 tests | 6 skipped) 8ms 275 MB heap used ↓ Internal notification CRUD (integration) > creates notification with metadata and default locale ↓ Internal notification CRUD (integration) > supports locale preference during creation ↓ Internal notification CRUD (integration) > paginates and filters notifications ↓ Internal notification CRUD (integration) > returns unread counts with category breakdown ↓ Internal notification CRUD (integration) > marks notification as read with timestamp and broadcast ↓ Internal notification CRUD (integration) > marks all notifications as read and soft deletes ✓ server/src/test/unit/workflowBundleCli.unit.test.ts (2 tests) 4ms 279 MB heap used ✓ server/src/test/unit/readAssistantContentFromSse.test.ts (1 test) 1ms 281 MB heap used ✓ packages/billing/tests/draftContractsActions.test.ts (6 tests) 19ms 288 MB heap used ✓ packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts (5 tests) 0ms 291 MB heap used ✓ packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (6 tests) 1ms 298 MB heap used ✓ sdk/samples/component/scheduler-demo/tests/handler.test.ts (6 tests) 1ms 302 MB heap used ✓ server/src/test/unit/api/chatExecute.route.gating.test.ts (1 test) 4ms 251 MB heap used packages/msp-composition/src/scheduling/MspSchedulingProvider.test.tsx (2 tests | 2 failed) 1ms 257 MB heap used × MspSchedulingProvider > provides renderAgentSchedule that returns AgentScheduleView 0ms → document is not defined × MspSchedulingProvider > provides launchTimeEntry that calls launchTimeEntryForWorkItem 0ms → document is not defined ✓ packages/scheduling/tests/scheduleEntry.test.ts (16 tests) 4ms 266 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerShell.fitSection.test.ts (11 tests) 1ms 276 MB heap used 2026-02-12T19:54:19.842538Z WARN temporalio_sdk_core::worker:💓 Worker heartbeating configured for runtime, but server version does not support it. 2026-02-12T19:54:20.240112Z WARN temporalio_sdk_core::worker:💓 Worker heartbeating configured for runtime, but server version does not support it. 2026-02-12T19:54:20.597915Z WARN temporalio_sdk_core::worker:💓 Worker heartbeating configured for runtime, but server version does not support it. ✓ ee/temporal-workflows/src/workflows/portal-domains/tests/registration.workflow.integration.test.ts (3 tests) 1776ms 430 MB heap used ✓ portalDomainRegistrationWorkflow > marks the domain as certificate_failed when ACME registration fails 343ms ✓ portalDomainRegistrationWorkflow > moves the domain to deploying after applying resources 1062ms ✓ portalDomainRegistrationWorkflow > retries after a failure and succeeds on the next attempt 371ms stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ ee/server/src/tests/unit/schedulerHostApi.unit.test.ts (72 tests) 6ms 424 MB heap used ✓ ee/server/src/lib/extensions/tests/manifest-v2.schema.test.ts (5 tests) 1ms 433 MB heap used stdout | server/src/test/integration/emailProviderCreation.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/src/components/invoice-designer/state/designerStore.size.test.ts (4 tests) 4ms 294 MB heap used stdout | shared/lib/utils/contentConversion.test.ts > convertHtmlToBlockNote > should handle linked images (image inside anchor) Linked Image Result: { "type": "link", "href": "https://google.com", "content": [ { "type": "text", "text": "🖼️ Logo", "styles": {} } ] }

✓ shared/lib/utils/contentConversion.test.ts (14 tests) 7ms 300 MB heap used ✓ server/src/test/unit/mention-detection.test.ts (12 tests) 1ms 304 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewModel.test.ts (5 tests) 1ms 313 MB heap used server/src/test/infrastructure/billing/invoices/clientBillingCycle.test.ts (1 test | 1 skipped) 2ms 319 MB heap used ↓ Client Billing Cycle Creation > creates a monthly billing cycle if none exists stdout | server/src/test/integration/emailProviderDatabase.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderDatabase.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderDatabase.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderDatabase.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/emailProviderDatabase.test.ts (6 tests | 6 skipped) 1ms 337 MB heap used ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should create a Google provider record in the database ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should handle Google Workspace email addresses ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should update an existing Google provider ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should list all Google providers for a tenant ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should handle provider creation with all optional fields ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should enforce database constraints stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/surveyEmailTemplates.integration.test.ts (2 tests | 2 skipped) 2ms 342 MB heap used ↓ Survey email templates > registers system templates for each supported locale ↓ Survey email templates > renders locale-specific content and falls back to English ✓ packages/billing/src/components/invoice-designer/state/designerStore.layoutMode.test.ts (2 tests) 3ms 354 MB heap used ✓ server/src/test/unit/resendWebhookEvents.test.ts (8 tests) 2ms 300 MB heap used stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/imports/FieldMapper.test.ts (2 tests) 1ms 333 MB heap used stdout | server/src/test/unit/db/workDate.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/db/workDate.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/db/workDate.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/db/workDate.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/db/workDate.test.ts (1 test) 3ms 339 MB heap used stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🏗️ Initializing Email Settings Test Fixture (one-time setup)... 📊 Setting up database and services... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🧹 Final test fixture cleanup...

server/src/test/e2e/email-settings/oauth-flow.test.ts (7 tests | 7 skipped) 3ms 352 MB heap used ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should complete OAuth flow and store tokens ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle OAuth error scenarios ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle Microsoft webhook validation token ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should complete OAuth flow with Pub/Sub setup ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should handle expired refresh token ↓ Email Settings OAuth Flow Tests > Token Storage and Encryption > should store tokens securely in database ↓ Email Settings OAuth Flow Tests > State Parameter Validation > should validate state parameter in OAuth callback stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.

shared/services/email/tests/EmailWebhookMaintenanceService.test.ts (3 tests | 1 failed) 2ms 362 MB heap used ✓ EmailWebhookMaintenanceService > should find candidates and renew expired subscription 0ms × EmailWebhookMaintenanceService > should recreate subscription if renewal fails with 404 1ms → expected "spy" to be called with arguments: [ 'https://api.example.com/webhook' ]

Number of calls: 0

✓ EmailWebhookMaintenanceService > should handle unexpected errors gracefully 0ms ✓ packages/auth/src/lib/session.test.ts (6 tests) 3ms 350 MB heap used stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/emailProviderErrorMessages.test.ts (10 tests | 10 skipped) 1ms 360 MB heap used ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error when provider name is missing ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error when email is invalid ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error when Google Client ID is missing ↓ Email Provider Error Messages > User-Friendly Error Messages > should return multiple errors in a clear format ↓ Email Provider Error Messages > User-Friendly Error Messages > should return helpful error for invalid provider type ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error for provider name that is too long ↓ Email Provider Error Messages > User-Friendly Error Messages > should return helpful error for invalid Microsoft tenant ID ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error for invalid max emails per sync ↓ Email Provider Error Messages > User-Friendly Error Messages > should return helpful hint for Google Client ID format ↓ Email Provider Error Messages > User-Friendly Error Messages > should successfully create provider when all fields are valid stdout | server/src/test/unit/templateRenderer.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/templateRenderer.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/templateRenderer.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/templateRenderer.test.tsx Retrieved secret 'db_password_server' from configured provider.

✓ tools/nx-tests/nxCache.test.ts (2 tests) 3726ms 356 MB heap used ✓ nx caching > reuses the local computation cache for repeated builds 732ms ✓ nx caching > caches @alga-psa/core builds when unchanged 2994ms ee/temporal-workflows/src/activities/tests/email-activities-simple.test.ts (24 tests | 17 failed) 916ms 365 MB heap used × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with default length of 12 0ms → expected Promise{…} to have property 'length' × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with custom length 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate different passwords each time 0ms × Email Activities - Simple Tests > generateTemporaryPassword > should contain at least one character from each category 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should not contain ambiguous characters 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should handle minimum length of 4 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate secure passwords with high entropy 0ms × Email Activities - Simple Tests > MockEmailService > should send emails successfully 102ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should validate email addresses correctly 0ms × Email Activities - Simple Tests > MockEmailService > should track sent emails for testing 101ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should filter emails by recipient 102ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should simulate failures when configured 101ms × Email Activities - Simple Tests > MockEmailService > should handle invalid email addresses 101ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle multiple recipients 101ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should throw error when no valid recipients 101ms × Email Activities - Simple Tests > MockEmailService > should support email service configuration 0ms → expected Promise{…} to be an instance of MockEmailService ✓ Email Activities - Simple Tests > MockEmailService > should return email templates for testing 0ms ✓ Email Activities - Simple Tests > MockEmailService > should return null for unknown templates 0ms × Email Activities - Simple Tests > MockEmailService > should support clearing sent emails 101ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle delay configuration 102ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > Email Service Factory > should create mock service by default 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should create mock service when explicitly requested 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should throw error for unknown providers 0ms → expected [Function] to throw an error × Email Activities - Simple Tests > Email Service Factory > should pass options to mock service 0ms → expected Promise{…} to be an instance of MockEmailService ✓ tools/nx-tests/moduleBoundaries.test.ts (2 tests) 6ms 382 MB heap used ✓ packages/client-portal/src/actions/client-portal-actions/client-tickets.ticketOrigin.test.ts (4 tests) 15ms 392 MB heap used packages/core/src/index.test.ts (1 test | 1 failed) 48ms 303 MB heap used × @alga-psa/core public exports > exports logger, secrets, events, and encryption APIs 48ms → expected 'undefined' to be 'function' // Object.is equality ✓ server/src/test/integration/emailProviderIntegration.test.ts (11 tests) 5ms 313 MB heap used stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts > CalendarProviderService encryption helpers > encrypts and decrypts Microsoft provider credentials CompositeSecretProvider: app secret 'calendar_oauth_encryption_key' not found in any provider

stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts > CalendarProviderService encryption helpers > encrypts and decrypts Microsoft provider credentials Secret 'calendar_oauth_encryption_key' not found via provider, checking env var 'CALENDAR_OAUTH_ENCRYPTION_KEY'.

✓ server/src/test/unit/calendar/CalendarProviderEncryption.test.ts (3 tests) 1ms 321 MB heap used stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts (6 tests | 6 skipped) 2ms 334 MB heap used ↓ emailLogActions.getEmailLogs > returns paginated results ↓ emailLogActions.getEmailLogs > filters by date range when provided ↓ emailLogActions.getEmailLogs > treats date-only endDate as inclusive end of day ↓ emailLogActions.getEmailLogs > filters by status when provided ↓ emailLogActions.getEmailLogs > filters by recipient email when provided ↓ emailLogActions.getEmailLogs > supports sorting by sent_at ascending/descending server/src/test/integration/onboardingProgressSubsteps.integration.test.ts (1 test | 1 failed) 1ms 339 MB heap used × getOnboardingProgressAction (substeps) > returns portal + email steps with substeps 1ms → Cannot find package '@alga-psa/onboarding/actions' imported from '/Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/server/src/test/integration/onboardingProgressSubsteps.integration.test.ts' ✓ ee/server/src/tests/unit/routeParams.resolveInstallId.test.ts (3 tests) 0ms 343 MB heap used ✓ packages/msp-composition/src/packageDependencies.test.ts (1 test) 0ms 347 MB heap used ✓ packages/tickets/src/lib/tests/ticketOrigin.test.ts (5 tests) 0ms 354 MB heap used ✓ packages/tickets/src/components/ticket/TicketDetails.originBadge.contract.test.ts (3 tests) 2ms 362 MB heap used packages/tickets/src/components/ticket/AgentScheduleDrawer.test.tsx (2 tests | 2 failed) 1ms 317 MB heap used × AgentScheduleDrawer > renders calendar when provider is present 0ms → document is not defined × AgentScheduleDrawer > shows fallback alert when no provider is present 1ms → document is not defined server/src/test/integration/citusTenantFilterEmailProviders.integration.test.ts (2 tests | 2 failed) 2ms 321 MB heap used × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Microsoft webhook route 1ms → expected 'export { GET, POST } from '@alga-psa…' to contain '.where({ id: row.id, tenant: row.tena…' × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Google webhook route 1ms → expected 'export { POST } from '@alga-psa/inte…' to contain '.where({ id: provider.id, tenant: pro…' stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/surveyTokenService.integration.test.ts (2 tests | 2 failed) 2ms 327 MB heap used × Survey Token Service integration > resolves invitation metadata for a valid survey token 0ms → × Survey Token Service integration > throws when the survey token has expired 0ms → ✓ packages/projects/src/lib/timeEntryContext.test.ts (1 test) 0ms 336 MB heap used ✓ server/src/test/unit/billing/billingCycleAnchors.validationMessages.test.ts (3 tests) 1ms 341 MB heap used ✓ packages/billing/tests/contractsTabs.test.ts (5 tests) 0ms 345 MB heap used stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ ee/server/src/tests/unit/invoicingInternalApi.unit.test.ts (1 test) 4ms 375 MB heap used stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/utils/utilities.test.ts (13 tests | 13 failed) 792ms 381 MB heap used × E2E Test Utilities > Test Environment Setup > should create a complete test environment 39ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have a valid database connection 52ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a tenant 38ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a user 52ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created an API key 30ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should generate random contact data 42ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create a single contact 56ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create multiple contacts 49ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should build query strings correctly 50ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert successful responses 215ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert error responses 80ms → no such database: test_database × E2E Test Utilities > API Client > should have API key configured 44ms → no such database: test_database × E2E Test Utilities > API Client > should be able to make requests 45ms → no such database: test_database ✓ ee/server/src/lib/extensions/tests/runner/backend.test.ts (4 tests) 11ms 388 MB heap used stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/portalDomainSessionOtt.test.ts (5 tests) 3ms 345 MB heap used ✓ packages/projects/tests/packageDependencies.test.ts (1 test) 0ms 350 MB heap used stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateDocumentPreviews] Generating previews for document doc-2 (image/png)

stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateImagePreviews] Image dimensions: 1200x900

stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateImagePreviews] Thumbnail generated: thumb-1

stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateImagePreviews] Preview generated: preview-2

stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > skips storage uploads for unsupported mime types [generateDocumentPreviews] Generating previews for document doc-1 (text/plain) [generateDocumentPreviews] Unsupported file type: text/plain

✓ server/src/test/unit/documentPreviewGenerator.test.ts (2 tests) 2ms 373 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.selectionState.test.ts (9 tests) 1ms 379 MB heap used stdout | server/src/test/e2e/email-processing.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-processing.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-processing.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-processing.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests 🧪 Initializing persistent E2E test context... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }

stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests 🧹 Cleaning up persistent E2E test context...

server/src/test/e2e/email-processing.test.ts (5 tests | 5 skipped) 2ms 350 MB heap used ↓ Email Processing E2E Tests > Basic Email Ingestion > should process a simple email and create a ticket ↓ Email Processing E2E Tests > Basic Email Ingestion > should handle emails with attachments ↓ Email Processing E2E Tests > Email Threading > should properly thread email replies ↓ Email Processing E2E Tests > Client Matching > should match emails to existing clients ↓ Email Processing E2E Tests > Client Matching > should handle unknown email addresses with manual fallback ✓ tools/nx-tests/nxAffected.test.ts (2 tests) 621ms 357 MB heap used ✓ nx affected > includes @alga-psa/clients when client code changes 334ms ↓ server/src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.ts (1 test | 1 skipped) ✓ server/src/test/unit/enterpriseAliasEnvSwitch.unit.test.ts (2 tests) 197ms 369 MB heap used server/src/test/integration/internal-notifications/eventSubscribers.integration.test.ts (14 tests | 14 skipped) 2ms 375 MB heap used ↓ internal notification event subscriber registration > subscribes to all expected event types on the internal channel ↓ internal notification event handling > creates notification for ticket assignment events targeting the assignee ↓ internal notification event handling > creates notifications for ticket additional agent assignments (agent, primary assignee, and client) ↓ internal notification event handling > does not invoke notification creation for events without handlers ↓ internal notification event handling > creates notifications for ticket created events for assignee and portal contact ↓ internal notification event handling > creates status change notifications for ticket updated events ↓ internal notification event handling > creates notifications for ticket closed events including client portal user ↓ internal notification event handling > creates project created notifications for assigned user ↓ internal notification event handling > creates project assigned notifications ↓ internal notification event handling > creates project task assigned notifications ↓ internal notification event handling > creates project task additional agent notifications for the new agent and the primary assignee ↓ internal notification event handling > creates invoice generated notifications ↓ internal notification event handling > creates message sent notifications for recipients ↓ internal notification event handling > creates document mention notifications server/src/test/unit/clientContractActions.overlapExclusive.test.ts (3 tests | 3 failed) 2ms 380 MB heap used × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (start == invoiced period end) 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (end exclusive == invoiced period start) 1ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > rejects true overlaps with an invoiced period 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package ✓ server/src/test/unit/RightSidebar.streaming.test.tsx (1 test) 486ms 87 MB heap used ✓ RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 485ms packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 52ms 118 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 32ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

✓ packages/projects/tests/projectInfoDrawer.test.tsx (1 test) 43ms 77 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 7 failed) 4053ms 113 MB heap used × ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 1003ms → Found multiple elements with the text: AI Assistant

Here are the matching elements:

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

Ignored nodes: comments, script, style <div class="font-medium" > AI Assistant 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke...

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke... × ExperimentalFeaturesSettings > defaults AI Assistant toggle to off 3ms → expected 'true' to be 'false' // Object.is equality × ExperimentalFeaturesSettings > renders experimental features warning banner 1004ms → Found multiple elements with the text: Experimental

Here are the matching elements:

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke...

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke... × ExperimentalFeaturesSettings > calls updateExperimentalFeatures() with current toggle states on save 1007ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke...

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke... × ExperimentalFeaturesSettings > shows success feedback after saving 1009ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke...

Ignored nodes: comments, script, style  

 <div class="space-y-2 mb-1" > <div class="flex items-center justify-between" > <div class="flex items-center space-x-5" > 
 ← Back to Projects 
 <span class="text-sm font-medium text-gray-600" > PRJ-100  <h1 class="text-xl font-bold" > Test Project  
 <div class="flex items-center gap-2" > <button id="save-as-template-button" type="button" variant="outline" > <svg class="lucide lucide-save h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save as Template  <button id="project-materials-button" type="button" variant="outline" > Materials  <button id="edit-project-button" type="button" variant="outline" > <svg class="lucide lucide-pen h-4 w-4 mr-2" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" />  Edit    <div class="flex items-center space-x-8" > <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Client:  <p class="text-base text-gray-800" > Client One 

  <div class="flex items-center space-x-2" > <h5 class="font-bold text-gray-800" > Contact:  <p class="text-base text-gray-800" > N/A 

  <div class="flex items-center space-x-2 flex-1" > <h5 class="font-bold text-gray-800" > Budget:  <div class="flex items-center space-x-3 flex-1" > <span class="text-base text-gray-800 whitespace-nowrap" > 0.0  of  0.0  hours  <div class="flex-1" />      
 <div class="rounded-lg border bg-card text-card-foreground shadow-sm " > <div class="flex flex-col space-y-1.5 p-6 undefined" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Experimental Features  <p class="text-sm text-muted-foreground undefined" > Enable or disable experimental features for your tenant. 

 
 <div class="p-6 pt-0 space-y-3" > <div class="relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 border-l-4 border-l-warning border-y-0 border-r-0 text-[rgb(var(--color-text-800))] [&>svg]:text-warning bg-warning/10" role="alert" > <svg class="lucide lucide-triangle-alert h-4 w-4" fill="none" height="24" stroke... ✓ ExperimentalFeaturesSettings > updates local state when toggled 11ms ✓ ExperimentalFeaturesSettings > loads current settings on mount 3ms × ExperimentalFeaturesSettings > renders list of features with toggles 8ms → expected [ <button …(8)>…(1), …(3) ] to have a length of 2 but got 4 × ExperimentalFeaturesSettings > disables AI Assistant toggle when not allowed 4ms → expected 'true' to be 'false' // Object.is equality ✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 1ms 116 MB heap used ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests) 115ms 129 MB heap used ✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 960ms 113 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 308ms ✓ EmailLogsClient > updates results when recipient search changes 308ms ✓ EmailLogsClient > updates results when ticket filter changes 310ms stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 166ms 140 MB heap used ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 249ms 294 MB heap used stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 219ms 308 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 35ms 342 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.constraintHighlights.test.tsx (2 tests) 3ms 347 MB heap used ✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 2ms 331 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1559ms 376 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 316ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 619ms ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1264ms 271 MB heap used stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' } iframeBridge: posting apiproxy_response { requestId: 'req-123', targetOrigin: '*' }

ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 3 failed) 141ms 254 MB heap used × Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 58ms → expected "spy" to be called with arguments: [ StringContaining{…}, …(1) ]

Number of calls: 0

✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 57ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 3ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 24ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests | 3 failed) 92ms 264 MB heap used ✓ TicketEmailNotifications > renders without errors 1ms ✓ TicketEmailNotifications > is collapsed by default and expands on click 10ms ✓ TicketEmailNotifications > shows loading state while fetching 11ms × TicketEmailNotifications > displays timestamp, recipient, subject, and status for each log entry 12ms → Found multiple elements with the text: /2026/

Here are the matching elements:

Ignored nodes: comments, script, style <div class="min-w-0" > 1/1/2026 

Ignored nodes: comments, script, style  Jan 01, 2026, 7:00 AM 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... ✓ TicketEmailNotifications > shows error message for failed notifications 9ms × TicketEmailNotifications > shows maximum 20 entries initially with Load more when more exist 16ms → Found multiple elements with the role "table"

Here are the matching elements:

Ignored nodes: comments, script, style <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-center" >  Created  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-updated_at" > <div class="flex space-x-1 items-center" >  Last Modified  <span class="text-muted-foreground" >  ↓    <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_id" > <div class="flex space-x-1 items-center" >  Actions  <span class="text-muted-foreground" />     <tbody class="divide-y divide-gray-100" > <tr class=" bg-[rgb(var(--color-border-50))] cursor-default transition-colors

              "
>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-contract_name"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        Draft Alpha
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-client_name"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        Acme Co
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-created_at"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        12/31/2025
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-updated_at"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        1/1/2026
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-contract_id"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        <button
          aria-expanded="false"
          aria-haspopup="menu"
          class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group"
          data-state="closed"
          type="button"
        >
          <span
            class="sr-only"
          >
            Open menu
          </span>
          <svg
            class="lucide lucide-ellipsis-vertical h-4 w-4"
            fill="none"
            height="24"
            stroke="currentColor"
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            viewBox="0 0 24 24"
            width="24"
            xmlns="http://www.w3.org/2000/svg"
          >
            <circle
              cx="12"
              cy="12"
              r="1"
            />
            <circle
              cx="12"
              cy="5"
              r="1"
            />
            <circle
              cx="12"
              cy="19"
              r="1"
            />
          </svg>
        </button>
      </div>
    </div>
  </td>
</tr>

 

Ignored nodes: comments, script, style <table data-automation-id="ticket-email-notifications-table" >    Jan 01, 2026, 7:00 AM   user0@example.com   S0   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user1@example.com   S1   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user2@example.com   S2   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user3@example.com   S3   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user4@example.com   S4   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user5@example.com   S5   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user6@example.com   S6   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user7@example.com   S7   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user8@example.com   S8   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user9@example.com   S9   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user10@example.com   S10   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user11@example.com   S11   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user12@example.com   S12   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user13@example.com   S13   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user14@example.com   S14   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user15@example.com   S15   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user16@example.com   S16   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user17@example.com   S17   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user18@example.com   S18   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user19@example.com   S19   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —    

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × TicketEmailNotifications > Load more fetches additional entries 33ms → Found multiple elements with the role "table"

Here are the matching elements:

Ignored nodes: comments, script, style <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-center" >  Created  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-updated_at" > <div class="flex space-x-1 items-center" >  Last Modified  <span class="text-muted-foreground" >  ↓    <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_id" > <div class="flex space-x-1 items-center" >  Actions  <span class="text-muted-foreground" />     <tbody class="divide-y divide-gray-100" > <tr class=" bg-[rgb(var(--color-border-50))] cursor-default transition-colors

              "
>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-contract_name"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        Draft Alpha
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-client_name"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        Acme Co
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-created_at"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        12/31/2025
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-updated_at"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        1/1/2026
      </div>
    </div>
  </td>
  <td
    class="px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "
    data-automation-id="draft-contracts-table-cell-0-contract_id"
  >
    <div
      class="break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"
    >
      <div
        class="min-w-0"
      >
        <button
          aria-expanded="false"
          aria-haspopup="menu"
          class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group"
          data-state="closed"
          type="button"
        >
          <span
            class="sr-only"
          >
            Open menu
          </span>
          <svg
            class="lucide lucide-ellipsis-vertical h-4 w-4"
            fill="none"
            height="24"
            stroke="currentColor"
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            viewBox="0 0 24 24"
            width="24"
            xmlns="http://www.w3.org/2000/svg"
          >
            <circle
              cx="12"
              cy="12"
              r="1"
            />
            <circle
              cx="12"
              cy="5"
              r="1"
            />
            <circle
              cx="12"
              cy="19"
              r="1"
            />
          </svg>
        </button>
      </div>
    </div>
  </td>
</tr>

 

Ignored nodes: comments, script, style <table data-automation-id="ticket-email-notifications-table" >    Jan 01, 2026, 7:00 AM   user0@example.com   S0   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user1@example.com   S1   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user2@example.com   S2   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user3@example.com   S3   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user4@example.com   S4   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user5@example.com   S5   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user6@example.com   S6   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user7@example.com   S7   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user8@example.com   S8   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user9@example.com   S9   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user10@example.com   S10   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user11@example.com   S11   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user12@example.com   S12   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user13@example.com   S13   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user14@example.com   S14   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user15@example.com   S15   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user16@example.com   S16   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user17@example.com   S17   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user18@example.com   S18   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user19@example.com   S19   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user20@example.com   S20   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user21@example.com   S21   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user22@example.com   S22   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user23@example.com   S23   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —     Jan 01, 2026, 7:00 AM   user24@example.com   S24   <span class="inline-flex items-center gap-2" > <span aria-hidden="true" class="h-2 w-2 rounded-full bg-emerald-500" /> <span class="capitalize" > sent     —    

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rounded-lg border bg-card text-card-foreground shadow-sm bg-white" > <div class="flex flex-col space-y-1.5 p-6 pb-2" > <div class="flex flex-row items-center justify-between" > <h3 class="text-lg font-semibold leading-none tracking-tight undefined" > Notes & Quick Info  <button class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group" type="button" > <svg class="lucide lucide-save" fill="none" height="14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="14" xmlns="http://www.w3.org/2000/svg" > <path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" /> <path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" /> <path d="M7 3v4a1 1 0 0 0 1 1h7" />  Save  
  <div class="p-6 pt-0 undefined" > <div class="min-h-[200px]" />    
 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > ... ✓ server/src/test/unit/QuickAskOverlay.streaming.test.tsx (1 test) 13ms 282 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 9 failed) 31ms 266 MB heap used × EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l6" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l7" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l8" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > aborts the streaming request when Stop is clicked 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l6" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l7" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > stops updating token display and ends generation state after Stop 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > shows a streaming cursor while receiving tokens 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l6" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > removes the streaming cursor when done is received 5ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l4" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l5" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > shows the partial response when a network error occurs mid-stream 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > shows an interruption indicator when the stream ends without done=true 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l3" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > persists the assistant message after streaming completes 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... × EE Chat (streaming state) > persists assistant content matching the final streamed tokens 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_kv" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l0" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l1" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_l2" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style  

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
  Templates <span data-testid="tab-icon-Templates" />   Client Contracts <span data-testid="tab-icon-Client Contracts" />   Drafts <span data-testid="tab-icon-Drafts" > <div class="inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border ml-2 order-last bg-gray-100 text-gray-800" > 1 
   
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
   <div class="datatable-container overflow-hidden bg-background rounded-lg border border-border" data-automation-id="draft-contracts-table" > <div class="overflow-x-auto" > <table class="w-full divide-y divide-[rgb(var(--color-border-200))]" > <thead class="bg-background" >  <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-contract_name" > <div class="flex space-x-1 items-center" >  Contract Name  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-client_name" > <div class="flex space-x-1 items-center" >  Client  <span class="text-muted-foreground" />   <th class="px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left" id="draft-contracts-table-header-created_at" > <div class="flex space-x-1 items-cen... ✓ packages/billing/src/components/invoice-designer/DesignerShell.constraints.test.tsx (23 tests) 461ms 330 MB heap used

Test Files 511 failed | 86 passed | 4 skipped (601) Tests 144 failed | 562 passed | 195 skipped (901) Start at 14:53:51 Duration 53.99s (transform 2.69s, setup 344ms, collect 2.87s, tests 40.94s, environment 244ms, prepare 47ms) (pass).

2026-02-12 — T014 implemented

  • Marked byte-for-byte deterministic evaluator output as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::returns byte-for-byte stable output for equivalent AST and input data

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T015 implemented

  • Marked renderer HTML coverage for text/field/table/totals compositions as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx::renders HTML for text/field/table/totals node combinations

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T016 implemented

  • Marked renderer style/class token consistency coverage as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx::applies class tokens and style declarations consistently

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T017 implemented

  • Marked unsafe text escaping behavior in renderer output as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx::escapes unsafe text content in rendered HTML

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T018 implemented

  • Marked server HTML wrapper coverage for headless PDF rendering as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/server-render.test.ts::returns a full HTML document wrapper

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T019 implemented

  • Marked designer workspace export-to-AST integration coverage as implemented.
  • Evidence: packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts::exports designer workspace to a versioned AST document

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T020 implemented

  • Marked AST hydration back into designer workspace as implemented.
  • Evidence: packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts::hydrates a designer workspace from persisted AST

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).

2026-02-12 — T004 implemented

  • Marked transform payload shape enforcement coverage as implemented for filter/sort/group/aggregate/computed operations.
  • Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::enforces transform payload shapes

Verification:

  • \WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})

RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770926085818"

Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 999 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should initialize with Redis client [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should warn if initialized twice [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Shutdown complete

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-2', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-2', remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return full bucket for new tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 100 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }

stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }

✓ server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts (17 tests) 7ms 15 MB heap used stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/googleProviderDataPersistence.test.ts (6 tests | 6 skipped) 19ms 90 MB heap used ↓ Google Provider Data Persistence Tests > should create a Google provider record with all required fields in the database ↓ Google Provider Data Persistence Tests > should persist Google Workspace (non-gmail.com) configurations correctly ↓ Google Provider Data Persistence Tests > should store OAuth tokens and authentication data when provided ↓ Google Provider Data Persistence Tests > should enforce proper database constraints for Google providers ↓ Google Provider Data Persistence Tests > should enforce validation for required fields ↓ Google Provider Data Persistence Tests > should correctly handle updates to existing Google provider configurations server/src/test/unit/Chat.streamingEndpoint.test.ts (2 tests | 1 failed) 3ms 97 MB heap used ✓ EE Chat (source) > uses the streaming completions endpoint for new messages 0ms × EE Chat (source) > reads the streaming response via response.body.getReader() 2ms → expected ''use client';\n\nimport React, { us…' to contain 'response.body.getReader()' ✓ packages/billing/src/actions/invoiceTemplateCompileParity.test.ts (2 tests) 0ms 100 MB heap used ✓ packages/billing/src/components/invoice-designer/state/designerStore.layout.test.ts (5 tests) 3ms 104 MB heap used ✓ packages/tickets/src/lib/timeEntryContext.test.ts (3 tests) 1ms 106 MB heap used ✓ server/src/test/unit/scheduling/eligibleSubjects.test.ts (3 tests) 1ms 107 MB heap used ✓ shared/workflow/runtime/tests/mappingResolver.test.ts (18 tests) 5ms 114 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerShell.fitSection.test.ts (11 tests) 1ms 123 MB heap used stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (4 tests) 8ms 220 MB heap used server/src/test/integration/ticketBundling.integration.test.ts (8 tests | 8 skipped) 1ms 231 MB heap used ↓ Ticket bundling integration > enforces permissions for bundle operations ↓ Ticket bundling integration > creates bundles, manages membership, and enforces invariants ↓ Ticket bundling integration > supports promote-to-master and preserves membership ↓ Ticket bundling integration > sync_updates propagates workflow changes; children lock workflow fields ↓ Ticket bundling integration > sync_updates mirrors public comments to children, marking them system-generated and immutable ↓ Ticket bundling integration > reopen-on-reply can reopen the master when a client replies on a child ↓ Ticket bundling integration > surfaces inbound child public replies on the master as aggregated view-only items ↓ Ticket bundling integration > blocks time entries on bundled children and allows time entries on masters stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/core/src/lib/events/publisher.test.ts (1 test) 4ms 239 MB heap used stdout | server/src/test/integration/emailProviderCreation.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts (7 tests | 7 skipped) 2ms 251 MB heap used ↓ createContractTemplateFromWizard with Currency Support > creates a template with USD currency and persists it correctly ↓ createContractTemplateFromWizard with Currency Support > creates a template with EUR currency and persists it correctly ↓ createContractTemplateFromWizard with Currency Support > creates a template with GBP currency and persists it correctly ↓ createContractTemplateFromWizard with Currency Support > creates templates with multiple currencies in same tenant ↓ createContractTemplateFromWizard with Currency Support > creates draft template with currency and verifies status and currency ↓ createContractTemplateFromWizard with Currency Support > creates contract from template and inherits template currency (EUR) ↓ createContractTemplateFromWizard with Currency Support > creates contract with JPY currency from template and preserves currency packages/core/src/lib/logger.outputs.test.ts (2 tests | 2 failed) 3ms 257 MB heap used × logger outputs > defaults to console-only transport 1ms → Target cannot be null or undefined. × logger outputs > configures external and file transports when enabled 1ms → Cannot read properties of undefined (reading 'find') stdout | server/src/lib/workflow/visualization/ast/flowGraphBuilder.test.ts > flowGraphBuilder > buildFlowGraph > should skip edges that involve state transitions Sorted components by source location: [ 'action at line 2:1' ] Sequential edge: connecting action-action1-2-1 (handle: right) to action-action1-2-1 (handle: left)

stdout | server/src/lib/workflow/visualization/ast/flowGraphBuilder.test.ts > flowGraphBuilder > buildFlowGraph > should exclude state transitions from the graph Sorted components by source location: [ 'action at line 3:1' ]

server/src/lib/workflow/visualization/ast/flowGraphBuilder.test.ts (3 tests | 2 failed) 55ms 275 MB heap used ✓ flowGraphBuilder > buildFlowGraph > should exclude state transitions from the graph 0ms × flowGraphBuilder > buildFlowGraph > should skip edges that involve state transitions 1ms → expected 'action-action1-2-1' to be 'action-0' // Object.is equality × flowGraphBuilder > applyLayout > should position nodes in a directed layout 53ms → expected 12 to be +0 // Object.is equality ✓ packages/billing/src/lib/invoice-template-ast/server-render.test.ts (1 test) 1ms 247 MB heap used ✓ packages/core/src/lib/logger.test.ts (1 test) 0ms 249 MB heap used packages/ui/src/context/SchedulingContext.test.tsx (4 tests | 4 failed) 1ms 275 MB heap used × SchedulingContext > returns default callbacks when no provider is present 1ms → document is not defined × SchedulingContext > renders fallback alert element for agent schedule by default 0ms → document is not defined × SchedulingContext > shows a toast when launching time entry without provider 0ms → document is not defined × SchedulingContext > uses provider callbacks when SchedulingCallbackProvider is present 0ms → document is not defined ✓ packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts (2 tests) 0ms 286 MB heap used ✓ server/src/test/unit/ui/timeTrackingSubjectSelector.test.ts (3 tests) 1ms 287 MB heap used stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts (7 tests | 7 skipped) 2ms 297 MB heap used ↓ email_sending_logs entity context migrations > adds entity_type column ↓ email_sending_logs entity context migrations > adds entity_id column ↓ email_sending_logs entity context migrations > adds contact_id column ↓ email_sending_logs entity context migrations > adds notification_subtype_id column ↓ email_sending_logs entity context migrations > creates tenant/entity index ↓ email_sending_logs entity context migrations > creates tenant/contact index ↓ email_sending_logs entity context migrations > migration files export up/down functions ✓ packages/tickets/src/lib/tests/responseSource.test.ts (8 tests) 0ms 266 MB heap used stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService REST usage > refreshes OAuth tokens when expired Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials

stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService REST usage > retries after 401 by refreshing token once and logs tenant metadata Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials

server/src/test/unit/accounting/xeroClientService.spec.ts (8 tests | 1 failed) 4ms 271 MB heap used ✓ XeroClientService REST usage > POST /Invoices payload matches spec requirements 0ms ✓ XeroClientService REST usage > normalizes validation errors returned from POST /Invoices 0ms ✓ XeroClientService REST usage > handles empty payload array without issuing network request 0ms ✓ XeroClientService REST usage > sets expected headers for authenticated requests 0ms ✓ XeroClientService REST usage > refreshes OAuth tokens when expired 1ms ✓ XeroClientService REST usage > retrieves accounts, items, tax rates, and tracking categories with normalized structures 1ms × XeroClientService REST usage > retries after 401 by refreshing token once and logs tenant metadata 1ms → expected "spy" to be called 1 times, but got 0 times ✓ XeroClientService REST usage > allows re-export after validation error once mappings are corrected 0ms stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":"PO-XYZ"} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""},{"type": "Text", "content": "PO #: PO-XYZ", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}

stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":null} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}

✓ server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts (1 test) 1355ms 282 MB heap used server/src/test/unit/tickets/TicketDetails.emailNotifications.integration.test.ts (1 test | 1 failed) 0ms 292 MB heap used × TicketDetails > includes the TicketEmailNotifications section 0ms → ENOENT: no such file or directory, open '/Users/roberisaacs/alga-psa.worktrees/codex/packages/tickets/src/components/ticket/TicketDetails.tsx' ✓ server/src/test/unit/extensions/uiHooks.test.ts (2 tests) 0ms 294 MB heap used stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts (5 tests | 5 skipped) 2ms 298 MB heap used ↓ Contract Purchase Order Support > T001: invoices table includes po_number + client_contract_id ↓ Contract Purchase Order Support > T002: invoice creation snapshots client_contracts.po_number onto invoices.po_number ↓ Contract Purchase Order Support > T003: invoice generation blocks when po_required=true and po_number is missing ↓ Contract Purchase Order Support > T004: PO consumption sums finalized invoices and unconsumes when status changes away from finalized ↓ Contract Purchase Order Support > T005: overage calculation uses invoice total_amount and contract po_amount (authorized total spend) stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/src/components/invoice-designer/state/designerStore.presets.test.ts (1 test) 3ms 311 MB heap used shared/workflow/actions/tests/emailWorkflowActions.responseSource.test.ts (6 tests | 5 failed) 17ms 317 MB heap used × createCommentFromEmail response source metadata > T002: persists metadata.responseSource=inbound_email 16ms → trx is not a function × createCommentFromEmail response source metadata > T003: includes normalized provider type when available 0ms → trx is not a function × createCommentFromEmail response source metadata > google inbound flow resolves to inbound_email metadata source (T017) 0ms → trx is not a function × createCommentFromEmail response source metadata > microsoft inbound flow resolves to inbound_email metadata source (T018) 0ms → trx is not a function × createCommentFromEmail response source metadata > imap inbound flow resolves to inbound_email metadata source (T019) 0ms → trx is not a function ✓ createCommentFromEmail response source metadata > T020: keeps comment response-state semantics unchanged (still non-internal) 0ms stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/multiCurrencyGaps.integration.test.ts (8 tests | 8 skipped) 2ms 279 MB heap used ↓ Multi-Currency Gap Tests > CRITICAL: Prepayment credits should track currency > createPrepaymentInvoice should record currency on the credit transaction ↓ Multi-Currency Gap Tests > CRITICAL: Prepayment credits should track currency > createPrepaymentInvoice should record currency on the credit_tracking entry ↓ Multi-Currency Gap Tests > CRITICAL: Credit application should validate currency > applyCreditToInvoice should reject applying USD credit to EUR invoice ↓ Multi-Currency Gap Tests > HIGH: Credit listing should support currency filtering > listClientCredits should be able to filter credits by currency ↓ Multi-Currency Gap Tests > HIGH: Credit history should support currency filtering > getCreditHistory should return transactions with currency information ↓ Multi-Currency Gap Tests > MEDIUM: Mixed-currency contract creation > should warn when creating contract in different currency than existing active contract ↓ Multi-Currency Gap Tests > VERIFIED: Working currency functionality > billing engine correctly retrieves contract currency via join ↓ Multi-Currency Gap Tests > VERIFIED: Working currency functionality > clients.default_currency_code has NOT NULL constraint stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/roles.e2e.test.ts (16 tests | 16 skipped) 2ms 191 MB heap used ↓ Roles API E2E Tests > Basic CRUD Operations > should create a new role ↓ Roles API E2E Tests > Basic CRUD Operations > should list roles with pagination ↓ Roles API E2E Tests > Basic CRUD Operations > should get a specific role ↓ Roles API E2E Tests > Basic CRUD Operations > should update a role ↓ Roles API E2E Tests > Basic CRUD Operations > should delete a role ↓ Roles API E2E Tests > Permission Management > should assign permissions to a role ↓ Roles API E2E Tests > Permission Management > should get role permissions ↓ Roles API E2E Tests > Role Templates > should get available role templates ↓ Roles API E2E Tests > Role Cloning > should clone an existing role ↓ Roles API E2E Tests > Bulk Operations > should bulk create roles ↓ Roles API E2E Tests > Error Handling > should return 401 without API key ↓ Roles API E2E Tests > Error Handling > should return 403 without permission ↓ Roles API E2E Tests > Error Handling > should return 400 for invalid data ↓ Roles API E2E Tests > Error Handling > should return 404 for non-existent role ↓ Roles API E2E Tests > Error Handling > should prevent duplicate role names ↓ Roles API E2E Tests > Tenant Isolation > should not access roles from other tenants ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewModel.test.ts (5 tests) 1ms 195 MB heap used ✓ packages/types/src/exports.typecheck.test.ts (1 test) 0ms 196 MB heap used server/src/test/integration/onboardingProgressSubsteps.integration.test.ts (1 test | 1 failed) 1ms 201 MB heap used × getOnboardingProgressAction (substeps) > returns portal + email steps with substeps 1ms → Cannot find package '@alga-psa/onboarding/actions' imported from '/Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/server/src/test/integration/onboardingProgressSubsteps.integration.test.ts' stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/appointmentNotifications.integration.test.ts (29 tests | 29 skipped) 3ms 223 MB heap used ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment request received email to client ↓ Appointment Notification System Integration Tests > Email Notifications > should send new appointment request email to MSP staff ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment approved email with correct locale ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment declined email with reason ↓ Appointment Notification System Integration Tests > Email Notifications > should include tenant settings in all emails ↓ Appointment Notification System Integration Tests > Email Notifications > should replace template variables correctly ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notifications for MSP staff on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on approval ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on decline ↓ Appointment Notification System Integration Tests > Internal Notifications > should include correct link in notifications ↓ Appointment Notification System Integration Tests > Internal Notifications > should populate metadata correctly for staff notifications ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct schedule approvers ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct tenant settings ↓ Appointment Notification System Integration Tests > Helper Function Integration > should map contact to client user ID correctly ↓ Appointment Notification System Integration Tests > Helper Function Integration > should return null for non-existent contact ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format dates with correct locale ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format times with correct locale ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should send email notifications in different languages ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should format dates according to locale in notifications ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should default to English when locale is not supported ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should send cancellation notification to client ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should handle cancellation of already cancelled request gracefully ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include actionable metadata in staff notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include appropriate links for client notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should set correct notification types for different events ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should handle missing email addresses gracefully ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should batch notifications to multiple staff members efficiently ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should include all required data fields in notifications packages/documents/tests/storageService.workflowEvents.test.ts (2 tests | 1 failed) 2ms 229 MB heap used ✓ StorageService.uploadFile workflow events > publishes FILE_UPLOADED after creating the file record 0ms × StorageService.uploadFile workflow events > publishes DOCUMENT_DELETED after deleting the file record 1ms → expected "spy" to be called with arguments: [ ObjectContaining{…} ]

Received:

1st spy call:

@@ -1,12 +1,18 @@ [

  • ObjectContaining {
  • "ctx": ObjectContaining {
    
  •   "tenantId": "tenant-1",
    
  • {
  • "ctx": {
    
  •   "actor": {
    
  •     "actorType": "USER",
    
  •     "actorUserId": "a836a8b5-3df5-47b1-b49b-9a78f2b1a8a0",
      },
    
  •   "occurredAt": "2026-01-24T12:30:00.000Z",
    
  •   "tenantId": undefined,
    
  • },
    "eventType": "DOCUMENT_DELETED",
    
  • "payload": ObjectContaining {
    
  • "idempotencyKey": "document_deleted:14f1fbf4-17d6-4bdc-8d4b-0b2a2ff8f26a:2026-01-24T12:30:00.000Z",
    
  • "payload": {
      "deletedAt": "2026-01-24T12:30:00.000Z",
      "deletedByUserId": "a836a8b5-3df5-47b1-b49b-9a78f2b1a8a0",
      "documentId": "14f1fbf4-17d6-4bdc-8d4b-0b2a2ff8f26a",
    },
    
    },

Number of calls: 1

✔ T020: ticket-created-hello fixture loads and executes via harness (3.852542ms) ✔ T100: ticket-created-triage-comment fixture loads and executes via harness (1.193708ms) ✔ T101: ticket-created-auto-assign-by-priority fixture loads and executes via harness (1.122709ms) ✔ T102: ticket-created-vip-notify fixture loads and executes via harness (1.090625ms) ✔ T103: ticket-created-outage-escalate fixture loads and executes via harness (0.949917ms) ✔ T104: ticket-created-create-project-task fixture loads and executes via harness (1.035083ms) ✔ T105: ticket-created-assign-trycatch fixture loads and executes via harness (1.134667ms) ✔ T106: ticket-created-notify-multiple fixture loads and executes via harness (1.554667ms) ✔ T107: ticket-created-ignore-system fixture loads and executes via harness (0.582625ms) ✔ T108: ticket-assigned-acknowledge fixture loads and executes via harness (1.149166ms) ✔ T109: ticket-unassigned-return-to-triage fixture loads and executes via harness (0.907625ms) ✔ T110: ticket-status-waiting-on-customer-reminder fixture loads and executes via harness (0.686458ms) ✔ T111: ticket-reopened-notify-tech fixture loads and executes via harness (0.713333ms) ✔ T112: ticket-escalated-crm-note fixture loads and executes via harness (0.87275ms) ✔ T113: ticket-queue-after-hours-email fixture loads and executes via harness (0.759292ms) ✔ T114: ticket-tags-billing-route fixture loads and executes via harness (0.782583ms) stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > honors public base override [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: 'http://localhost:8085', runnerBase: undefined, publicBase: 'http://localhost:8085' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > falls back to /runner when no public base is set [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: undefined, publicBase: '/runner' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > appends tenant when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: null, runnerBase: undefined, publicBase: '/runner' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > uses absolute public base when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/settings', tenantId: undefined, overrideBase: null, runnerBase: 'https://runner.dev/alga', publicBase: 'https://runner.dev/alga' }

stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > supports relative public base for gateway proxy [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: '/runner', publicBase: '/runner' }

✓ ee/server/src/lib/extensions/tests/assets/url.shared.test.ts (5 tests) 1ms 240 MB heap used ✓ server/src/test/unit/notifications/emailRateLimiting.test.ts (14 tests) 1ms 244 MB heap used stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/boards.e2e.test.ts (10 tests | 10 skipped) 2ms 200 MB heap used ↓ Board API E2E Tests > Authentication > should require API key ↓ Board API E2E Tests > Authentication > should reject invalid API key ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should list active boards by default ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should include inactive boards when requested ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should support pagination ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should support search by name ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should sort by display_order by default ↓ Board API E2E Tests > Get Board by ID (GET /api/v1/boards/:id) > should retrieve a board by ID ↓ Board API E2E Tests > Get Board by ID (GET /api/v1/boards/:id) > should return 404 for non-existent board ↓ Board API E2E Tests > Get Board by ID (GET /api/v1/boards/:id) > should return 400 for invalid UUID format ee/extensions/samples/ui-kit-showcase/test/build.test.ts (1 test | 1 failed) 0ms 202 MB heap used × build output > iframe bundle is generated in ui/dist/iframe 0ms → expected false to be true // Object.is equality stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/api/chatExecute.route.gating.test.ts (1 test) 4ms 229 MB heap used stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/time-entries.e2e.test.ts (40 tests | 38 failed | 2 skipped) 41ms 213 MB heap used × Time Entries API E2E Tests > Authentication > should require API key for all endpoints 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Authentication > should reject invalid API key 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should start a tracking session 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should stop a tracking session 1ms → → Cannot read properties of undefined (reading 'cleanup') ↓ Time Entries API E2E Tests > Approval Workflow > should approve time entries ↓ Time Entries API E2E Tests > Approval Workflow > should reject invalid entry IDs for approval × Time Entries API E2E Tests > Export > should export time entries to CSV 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Export > should export time entries to JSON 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Statistics > should get time entry statistics 2ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Templates > should list time entry templates 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk create time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk update time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid UUID format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid query parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid date format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce read permissions for listing 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce create permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce update permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce delete permissions 7ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant 1ms → → Cannot read properties of undefined (reading 'cleanup') server/src/lib/eventBus/index.hardTimeout.test.ts (1 test | 1 failed) 4ms 221 MB heap used × EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout 4ms → Failed to resolve entry for package "@alga-psa/event-schemas". The package may have incorrect main/module/exports specified in its package.json. stdout | ee/server/src/tests/integration/ticket-response-state.integration.test.ts > Ticket Response State Integration Tests Database config: { host: 'localhost', port: 5438, database: 'server', user: 'app_user', password: '[32 chars]', ssl: false }

ee/server/src/tests/integration/ticket-response-state.integration.test.ts (28 tests | 28 skipped) 2ms 226 MB heap used ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T001: ticket_response_state enum type exists with correct values ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T002: response_state column exists on tickets table and is nullable ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T003: Index exists on (tenant, response_state) ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T004: New tickets have null response_state by default ↓ Ticket Response State Integration Tests > Type Definition Tests (T005-T006) > T005-T006: TicketResponseState type exists and allows correct values ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T007: Staff creates client-visible comment → response_state becomes awaiting_client ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T008: Staff creates client-visible comment on ticket already awaiting_client → state unchanged ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T009: Staff creates client-visible comment on ticket awaiting_internal → state becomes awaiting_client ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T010: Client creates comment → response_state becomes awaiting_internal ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T011: Client creates comment on ticket already awaiting_internal → state unchanged ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T012: Client creates comment on ticket awaiting_client → state becomes awaiting_internal ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T013: Staff creates internal note → response_state does not change from null ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T014: Staff creates internal note on awaiting_client ticket → state remains awaiting_client ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T015: Staff creates internal note on awaiting_internal ticket → state remains awaiting_internal ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T016-T017: Comment creation and response state update occur in same transaction ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T018: updateTicket with response_state=awaiting_client updates ticket ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T019: updateTicket with response_state=awaiting_internal updates ticket ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T020: updateTicket with response_state=null clears response state ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T022-T024: Closing ticket clears response_state ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T025: Closing ticket with null response_state keeps response_state null ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T026: Reopening closed ticket does not set response_state ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T054: TICKET_RESPONSE_STATE_CHANGED event type exists ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T055: Event schema validates required fields ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T056-T057: Creating client-visible comment fires TICKET_RESPONSE_STATE_CHANGED event with trigger=comment ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T063-T064: Event includes correct previousState and newState values ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T072: TICKET_COMMENT_ADDED event payload includes author_type ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T076: Internal note does not fire TICKET_RESPONSE_STATE_CHANGED event ↓ Ticket Response State Integration Tests > Tenant Isolation Tests (T073-T075) > T073-T074: Users cannot see or update response_state of tickets in other tenants server/src/test/integration/ticketEmailDelimiters.test.ts (21 tests | 21 skipped) 54ms 234 MB heap used ↓ sendEventEmail reply markers > adds reply markers when conversation token is provided ↓ sendEventEmail reply markers > generates a conversation token when one is not supplied ↓ sendEventEmail reply markers > includes comment and thread markers for comment notifications ↓ ticket email subscriber reply markers > processes ticket created events with delimiters ↓ ticket email subscriber reply markers > processes ticket updated events with delimiters ↓ ticket email subscriber reply markers > processes ticket comment events with comment markers ↓ ticket email subscriber event publishing > publishes ticket created events and emails the primary contact ↓ ticket email subscriber deduplication > sends only one ticket created email when primary and assigned recipients share address ↓ ticket email subscriber deduplication > sends one internal ticket assigned email when assignee and contact share address ↓ ticket email subscriber deduplication > sends one ticket assigned email when contact and location share address ↓ ticket email subscriber deduplication > sends one ticket assigned email when additional resource shares email with assignee ↓ ticket email subscriber deduplication > sends one ticket comment email when additional resource shares email with assignee ↓ ticket email subscriber notification gating (known gap) > skips ticket created email when tenant notifications are disabled ↓ ticket email subscriber notification gating (known gap) > skips ticket created email when subtype is disabled ↓ ticket email subscriber notification gating (known gap) > skips ticket assigned email when user preference is disabled ↓ ticket email subscriber link routing > uses portal domain for external recipients and MSP URL for internal users ↓ ticket email subscriber link routing > falls back to the client portal path when no custom domain exists ↓ ticket email subscriber rich text formatting > renders rich text comment content as HTML instead of JSON ↓ ticket email subscriber rich text formatting > renders ticket description rich text without leaking JSON ↓ project email subscriber rich text formatting > renders project description rich text in project created emails ↓ project email subscriber rich text formatting > renders project description rich text in project assigned emails stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🏗️ Initializing Email Settings Test Fixture (one-time setup)... 📊 Setting up database and services... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🧹 Final test fixture cleanup...

server/src/test/e2e/email-settings/oauth-flow.test.ts (7 tests | 7 skipped) 3ms 248 MB heap used ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should complete OAuth flow and store tokens ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle OAuth error scenarios ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle Microsoft webhook validation token ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should complete OAuth flow with Pub/Sub setup ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should handle expired refresh token ↓ Email Settings OAuth Flow Tests > Token Storage and Encryption > should store tokens securely in database ↓ Email Settings OAuth Flow Tests > State Parameter Validation > should validate state parameter in OAuth callback ✓ packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (2 tests) 0ms 260 MB heap used ✓ server/src/test/unit/api/chatCompletions.route.gating.test.ts (2 tests) 4ms 268 MB heap used ✓ server/src/test/unit/billingPlanSelection.test.ts (5 tests | 1 skipped) 1ms 276 MB heap used ✓ sdk/samples/extension-ui/service-proxy-demo/tests/fetch.test.ts (1 test) 0ms 279 MB heap used stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/surveyEmailTemplates.integration.test.ts (2 tests | 2 skipped) 1ms 253 MB heap used ↓ Survey email templates > registers system templates for each supported locale ↓ Survey email templates > renders locale-specific content and falls back to English stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts > GmailAdapter.listMessagesSince > attempts to recreate Gmail watch when historyId rejection occurs [GOOGLE] Attempting to recreate Gmail watch after history_id invalidation { providerId: 'provider-id', rejectedHistoryId: '31559633' }

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts > GmailAdapter.listMessagesSince > attempts to recreate Gmail watch when historyId rejection occurs [GOOGLE] Gmail watch recreated successfully after history_id invalidation

stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts > GmailAdapter.listMessagesSince > surfaces a dedicated error when Gmail returns historyId not found [GOOGLE] Attempting to recreate Gmail watch after history_id invalidation { providerId: 'provider-id', rejectedHistoryId: '31559633' }

✓ server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts (2 tests) 2ms 258 MB heap used ✓ server/src/app/api/client-portal/domain-session/route.test.ts (5 tests) 2ms 262 MB heap used tools/nx-tests/editionSwapping.test.ts (2 tests | 1 failed) 194ms 265 MB heap used × CE/EE build swapping > CE build excludes EE code in module resolution 97ms → expected '/Users/roberisaacs/alga-psa.worktrees…' to be '/Users/roberisaacs/alga-psa.worktrees…' // Object.is equality ✓ CE/EE build swapping > EE build includes EE code in module resolution 97ms ✓ server/src/test/unit/security/managerScopeRegression.test.ts (1 test) 1ms 267 MB heap used ✓ packages/core/src/lib/encryption.test.ts (2 tests) 2ms 270 MB heap used stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/utils/utilities.test.ts (13 tests | 13 failed) 566ms 295 MB heap used × E2E Test Utilities > Test Environment Setup > should create a complete test environment 54ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have a valid database connection 39ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a tenant 36ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a user 44ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created an API key 111ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should generate random contact data 37ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create a single contact 37ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create multiple contacts 38ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should build query strings correctly 31ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert successful responses 29ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert error responses 36ms → no such database: test_database × E2E Test Utilities > API Client > should have API key configured 43ms → no such database: test_database × E2E Test Utilities > API Client > should be able to make requests 31ms → no such database: test_database ✓ packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (6 tests) 1ms 304 MB heap used server/src/test/unit/contractLineDisambiguation.test.ts (12 tests | 6 failed) 4ms 310 MB heap used × Contract Line Disambiguation Logic > getEligibleContractLines > should query for eligible contract lines 1ms → knex is not a function × Contract Line Disambiguation Logic > determineDefaultContractLine > should return the only contract line when there is just one eligible contract line 0ms → expected null to be 'contractLine1' // Object.is equality ✓ Contract Line Disambiguation Logic > determineDefaultContractLine > should return null when there are no eligible contract lines 0ms × Contract Line Disambiguation Logic > determineDefaultContractLine > should return the contract line with a bucket overlay when there is only one overlay 0ms → expected null to be 'contractLine2' // Object.is equality ✓ Contract Line Disambiguation Logic > determineDefaultContractLine > should return null when there are multiple eligible contract lines with no clear default 0ms ✓ Contract Line Disambiguation Logic > determineDefaultContractLine > should return null when there are multiple contract lines with bucket overlays 0ms × Contract Line Disambiguation Logic > validateContractLineForService > should return true when the contract line is valid for the service 0ms → expected false to be true // Object.is equality ✓ Contract Line Disambiguation Logic > validateContractLineForService > should return false when the contract line is not valid for the service 0ms × Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return true when this is the only eligible contract line 0ms → expected false to be true // Object.is equality × Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return true when this is the only contract line with a bucket overlay 0ms → expected false to be true // Object.is equality ✓ Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return false when this is not the only eligible contract line and has no bucket overlay 0ms ✓ Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return false when there are multiple contract lines with bucket overlays 0ms ✓ packages/tickets/src/components/ticket/TicketDetails.scheduleDrawer.test.ts (1 test) 0ms 270 MB heap used ✓ packages/types/src/interfaces/ticket.interface.typecheck.test.ts (1 test) 0ms 273 MB heap used stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'db_password_server' from configured provider.

server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts (1 test | 1 skipped) 1ms 280 MB heap used ↓ Tax Rate Changes Mid-Billing Period > should apply correct tax rates based on charge dates ✓ packages/billing/src/lib/invoice-template-ast/evaluator.test.ts (13 tests) 4ms 292 MB heap used stdout | server/src/test/unit/billingEngine.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billingEngine.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billingEngine.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billingEngine.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ sdk/extension-runtime/tests/runtime.test.ts (3 tests) 1ms 326 MB heap used ✓ server/src/test/unit/ui/timesheetHeader.test.ts (1 test) 0ms 329 MB heap used server/src/test/integration/emailAttachmentIngestion.integration.test.ts (6 tests | 6 skipped) 4ms 293 MB heap used ↓ Email attachment ingestion (workflow-worker action override) > skips inline/CID attachments (no documents/files created) ↓ Email attachment ingestion (workflow-worker action override) > rejects attachments >100MB (no documents/files created) ↓ Email attachment ingestion (workflow-worker action override) > is idempotent: duplicate processing does not create duplicate documents/files ↓ Email attachment ingestion (workflow-worker action override) > skips unsupported Microsoft attachment types (records skipped) ↓ Email attachment ingestion (workflow-worker action override) > retries failed processing without duplicating records ↓ Email attachment ingestion (workflow-worker action override) > creates external_files + documents + document_associations with system attribution (Gmail path) ✓ sdk/samples/component/invoicing-demo/tests/handler.test.ts (4 tests) 1ms 297 MB heap used ✓ server/src/test/unit/DocumentationService.test.ts (4 tests) 1ms 300 MB heap used stdout | server/src/test/integration/emailProviderValidation.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderValidation.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderValidation.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderValidation.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/emailProviderValidation.test.ts (10 tests | 10 skipped) 1ms 312 MB heap used ↓ Email Provider Validation Tests > Google Provider Validation > should return error when missing required Google provider fields ↓ Email Provider Validation Tests > Google Provider Validation > should return error for invalid email format ↓ Email Provider Validation Tests > Google Provider Validation > should return error when provider name is too long ↓ Email Provider Validation Tests > Microsoft Provider Validation > should return error when missing required Microsoft provider fields ↓ Email Provider Validation Tests > Microsoft Provider Validation > should handle missing optional fields gracefully ↓ Email Provider Validation Tests > General Validation > should return error for null or undefined required fields ↓ Email Provider Validation Tests > General Validation > should return error for empty string in required fields ↓ Email Provider Validation Tests > General Validation > should handle special characters in provider names ↓ Email Provider Validation Tests > General Validation > should return meaningful error for duplicate mailbox ↓ Email Provider Validation Tests > Error Message Quality > should provide helpful error messages for common mistakes stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/SettingsPage.experimentalFeatures.lazy.test.ts (1 test) 855ms 409 MB heap used ✓ SettingsPage > loads Experimental Features tab lazily via next/dynamic 855ms ✓ packages/scheduling/tests/scheduleEntryRecurrence.test.ts (22 tests) 11ms 439 MB heap used packages/msp-composition/src/scheduling/MspSchedulingProvider.test.tsx (2 tests | 2 failed) 1ms 405 MB heap used × MspSchedulingProvider > provides renderAgentSchedule that returns AgentScheduleView 0ms → document is not defined × MspSchedulingProvider > provides launchTimeEntry that calls launchTimeEntryForWorkItem 1ms → document is not defined stdout | packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts > renderTemplateOnServer AST integration > renders template HTML/CSS from canonical AST payload [Server Action] Successfully rendered template: tpl-1

✓ packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts (2 tests) 2ms 414 MB heap used ✓ ee/server/src/tests/unit/tenant-creation.test.ts (4 tests) 0ms 425 MB heap used stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/api/tickets.e2e.test.ts (47 tests | 47 skipped) 79ms 441 MB heap used ↓ Ticket API E2E Tests > Authentication > should require API key for all endpoints ↓ Ticket API E2E Tests > Authentication > should reject invalid API key ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create a new ticket ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should validate required fields ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create ticket with all optional fields ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should retrieve a ticket by ID ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should return 404 for non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should not return tickets from other tenants ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should update a ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should return 404 when updating non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should validate update data ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should delete a ticket ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should return 404 when deleting non-existent ticket ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should list all tickets with default pagination ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should support pagination parameters ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by client_id ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by status ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by priority ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by assigned user ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter overdue tickets ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should sort tickets by created date ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search tickets by query ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search in specified fields ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should limit search results ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add a comment to a ticket ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add an internal comment ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should list ticket comments ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should return 404 when adding comment to non-existent ticket ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should update ticket status ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should validate status transitions ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should assign ticket to user ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should unassign ticket ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should return ticket statistics ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by date range ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by client ↓ Ticket API E2E Tests > Create Ticket from Asset (POST /api/v1/tickets/from-asset) > should create ticket from asset ↓ Ticket API E2E Tests > Error Handling > should handle invalid UUID format ↓ Ticket API E2E Tests > Error Handling > should handle invalid query parameters ↓ Ticket API E2E Tests > Error Handling > should handle missing required fields on create ↓ Ticket API E2E Tests > Error Handling > should handle invalid date formats ↓ Ticket API E2E Tests > Permissions > should enforce read permissions for GET endpoints ↓ Ticket API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE ↓ Ticket API E2E Tests > Permissions > should enforce assignment permissions ↓ Ticket API E2E Tests > Multi-tenancy > should isolate tickets by tenant ↓ Ticket API E2E Tests > Advanced Features > should support bulk operations ↓ Ticket API E2E Tests > Advanced Features > should support ticket templates ↓ Ticket API E2E Tests > Advanced Features > should track ticket history ✓ ee/server/src/lib/extensions/tests/gateway/gateway-utils.test.ts (13 tests) 2ms 445 MB heap used ✓ packages/tickets/src/actions/ticketActions.ticketOrigin.test.ts (4 tests) 20ms 455 MB heap used stdout | server/src/test/e2e/email-settings/email-threading.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/email-threading.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-settings/email-threading.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/email-threading.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests 🏗️ Initializing Email Settings Test Fixture (one-time setup)... 📊 Setting up database and services... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }

stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/e2e/email-settings/email-threading.test.ts (3 tests | 3 skipped) 2ms 465 MB heap used ↓ Email Threading Tests > Email to Ticket Flow > should create ticket from initial email ↓ Email Threading Tests > Reply Threading > should add reply as comment to existing ticket ↓ Email Threading Tests > Thread ID Preservation > should maintain thread ID across email exchanges stdout | packages/db/src/lib/tenantContext.test.ts > tenant context > createTenantKnex falls back to AsyncLocalStorage tenant context [db/tenant] Database configuration { client: 'postgres', connection: { host: 'localhost', port: 5432, database: 'db', user: 'user', password: 'pw' }, pool: {} }

stdout | packages/db/src/lib/tenantContext.test.ts > tenant context > createTenantKnex uses an explicit tenant id when provided [db/tenant] Database configuration { client: 'postgres', connection: { host: 'localhost', port: 5432, database: 'db', user: 'user', password: 'pw' }, pool: {} }

✓ packages/db/src/lib/tenantContext.test.ts (2 tests) 5ms 471 MB heap used ee/temporal-workflows/src/activities/tests/email-activities.temporal.test.ts (11 tests | 10 failed) 136ms 438 MB heap used × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should generate secure passwords with proper entropy 1ms → expected Promise{…} to have property 'length' × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should handle various password lengths correctly 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should ensure consistent randomness across calls 0ms × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should send welcome email with valid input 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle invalid email addresses gracefully 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle empty email addresses 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should work with minimal required fields 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should generate proper email content structure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should handle template variable substitution 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should not throw exceptions on failure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should handle missing required fields gracefully 0ms → Cannot read properties of undefined (reading 'info') ✓ shared/lib/utils/emailFileConversion.test.ts (4 tests) 4ms 446 MB heap used ee/extensions/samples/ui-kit-showcase/test/theme.test.tsx (3 tests | 3 failed) 1ms 450 MB heap used × theme bridge (postMessage) > applyTheme sets CSS variables on document root 0ms → document is not defined × theme bridge (postMessage) > message handler applies theme from Alga envelope format 0ms → document is not defined × theme bridge (postMessage) > ignores non-Alga messages 0ms → document is not defined stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/accounting/externalTaxImport.integration.test.ts (14 tests | 14 skipped) 2ms 462 MB heap used ↓ External Tax Import > importing tax from external accounting system > should update invoice charges with tax amounts from QuickBooks ↓ External Tax Import > importing tax from external accounting system > should change invoice tax_source from pending_external to external ↓ External Tax Import > importing tax from external accounting system > should create audit record in external_tax_imports table ↓ External Tax Import > importing tax from external accounting system > should update invoice total_amount to include imported tax ↓ External Tax Import > tax allocation across charges > should apply per-line tax amounts from external system ↓ External Tax Import > tax allocation across charges > should handle mix of taxable and non-taxable items ↓ External Tax Import > tax allocation across charges > should handle different tax rates across items ↓ External Tax Import > tax allocation across charges > should distribute proportionally when line matching fails ↓ External Tax Import > tax allocation across charges > should match by charge ID even when external lines are returned out of order ↓ External Tax Import > internal tax calculation is skipped for external delegation > should set tax to zero when invoice has pending_external tax source ↓ External Tax Import > automatic tax import after export > should automatically import tax after exporting invoice with tax delegation ↓ External Tax Import > error handling > should fail if invoice is not pending_external ↓ External Tax Import > error handling > should fail if invoice has no external mapping ↓ External Tax Import > error handling > should fail if external system returns error ✓ server/src/test/unit/internal-notifications/mentionParser.test.ts (28 tests) 2ms 467 MB heap used stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests Retrieved secret 'db_password_server' from configured provider.

server/src/test/integration/googleProviderDatabaseSave.test.ts (6 tests | 6 skipped) 2ms 479 MB heap used ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should save a complete Google provider configuration to the database ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should handle Gmail-specific email addresses correctly ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should handle Google Workspace custom domain emails ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should save OAuth tokens when provided ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should validate required fields for Google provider ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should properly format and save all Google-specific configuration options ✓ packages/client-portal/src/components/tickets/TicketDetails.originBadge.contract.test.ts (3 tests) 1ms 490 MB heap used stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.

shared/services/email/tests/EmailWebhookMaintenanceService.test.ts (3 tests | 1 failed) 2ms 506 MB heap used ✓ EmailWebhookMaintenanceService > should find candidates and renew expired subscription 0ms × EmailWebhookMaintenanceService > should recreate subscription if renewal fails with 404 1ms → expected "spy" to be called with arguments: [ 'https://api.example.com/webhook' ]

Number of calls: 0

✓ EmailWebhookMaintenanceService > should handle unexpected errors gracefully 1ms ee/server/extensions/samples/ui-kit-showcase/test/theme.test.tsx (3 tests | 3 failed) 0ms 461 MB heap used × theme bridge (postMessage) > applyTheme sets CSS variables on document root 0ms → document is not defined × theme bridge (postMessage) > message handler applies theme from Alga envelope format 0ms → document is not defined × theme bridge (postMessage) > ignores non-Alga messages 0ms → document is not defined ✓ packages/projects/tests/packageDependencies.test.ts (1 test) 0ms 465 MB heap used ✓ server/src/test/unit/services/numberingService.test.ts (5 tests) 1ms 470 MB heap used stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/services/chatCompletionsService.streaming.test.ts (1 test) 93ms 483 MB heap used stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage Retrieved secret 'db_password_server' from configured provider.

server/src/test/unit/email/outboundMessageIdStorage.test.ts (6 tests | 6 skipped) 1ms 493 MB heap used ↓ Outbound Message-ID Storage > Message-ID References Storage > should store outbound Message-ID in ticket email_metadata references array ↓ Outbound Message-ID Storage > Message-ID References Storage > should append multiple Message-IDs to references array ↓ Outbound Message-ID Storage > Message-ID References Storage > should initialize empty references array if email_metadata is null ↓ Outbound Message-ID Storage > Message-ID References Storage > should preserve existing email_metadata fields when adding references ↓ Outbound Message-ID Storage > Message-ID References Storage > should handle Message-ID format variations correctly ↓ Outbound Message-ID Storage > Message-ID Storage Integration > should support full email conversation thread via references ee/temporal-workflows/src/test-utils/test-connection.test.ts (3 tests | 1 failed) 118ms 499 MB heap used ✓ Temporal Connection Tests > should connect to temporalio/auto-setup Docker container 6ms ✓ Temporal Connection Tests > should create TestWorkflowEnvironment for unit tests 110ms × Temporal Connection Tests > should verify Docker Postgres connection 2ms → ✓ packages/msp-composition/src/packageDependencies.test.ts (1 test) 0ms 503 MB heap used stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/email/replyTokenExtraction.test.ts (10 tests) 3ms 519 MB heap used ✓ packages/billing/tests/deleteContractPermissions.test.ts (1 test) 23ms 465 MB heap used server/src/test/unit/workflow/visualization/astParser.test.ts (1 test | 1 failed) 457ms 651 MB heap used × AST Parser and Analyzer > should parse and analyze the invoice approval workflow 457ms → Could not find source file: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/src/lib/workflow/examples/invoiceApprovalWorkflow.ts ✓ server/src/test/integration/emailProviderIntegration.test.ts (11 tests) 6ms 662 MB heap used ✓ packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts (1 test) 0ms 666 MB heap used ✓ packages/ui/src/context/index.test.ts (1 test) 0ms 671 MB heap used stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.

server/src/lib/extensions/ui/iframeBridge.test.ts (5 tests | 5 failed) 3ms 673 MB heap used × bootstrapIframe (host bridge) > applies sandbox="allow-scripts" by default when none provided 0ms → window is not defined × bootstrapIframe (host bridge) > throws when allowedOrigin mismatches iframe src origin and RUNNER_PUBLIC_BASE is absolute 0ms → window is not defined × bootstrapIframe (host bridge) > sends bootstrap message with envelope version after load 0ms → window is not defined × bootstrapIframe (host bridge) > adjusts iframe height on resize messages with clamping 0ms → window is not defined × bootstrapIframe (host bridge) > validates contentHash format 1ms → window is not defined ✓ server/src/test/unit/workflowRunDialogEventUtils.test.ts (3 tests) 1ms 681 MB heap used

server@0.16.5 start:express tsx index.ts

server/src/test/e2e/api/clients.e2e.test.ts (22 tests | 22 skipped) 1007ms 692 MB heap used ↓ Clients API E2E Tests > Authentication > should reject requests without API key ↓ Clients API E2E Tests > Authentication > should reject requests with invalid API key ↓ Clients API E2E Tests > Authentication > should accept requests with valid API key ↓ Clients API E2E Tests > CRUD Operations > should create a client ↓ Clients API E2E Tests > CRUD Operations > should get a client by ID ↓ Clients API E2E Tests > CRUD Operations > should update a client ↓ Clients API E2E Tests > CRUD Operations > should delete a client ↓ Clients API E2E Tests > CRUD Operations > should list clients with pagination ↓ Clients API E2E Tests > Client Locations > should create a client location ↓ Clients API E2E Tests > Client Locations > should get client locations ↓ Clients API E2E Tests > Client Contacts > should get client contacts ↓ Clients API E2E Tests > Client Statistics > should get client statistics ↓ Clients API E2E Tests > Error Handling > should return 404 for non-existent client ↓ Clients API E2E Tests > Error Handling > should return 400 for invalid client data ↓ Clients API E2E Tests > Error Handling > should return 400 for invalid UUID ↓ Clients API E2E Tests > Filtering and Search > should filter clients by active status ↓ Clients API E2E Tests > Filtering and Search > should search clients by name ↓ Clients API E2E Tests > Inactive Client Behavior > should set all contacts and users to inactive when client is set to inactive ↓ Clients API E2E Tests > Inactive Client Behavior > should allow reactivating only the client, leaving contacts inactive ↓ Clients API E2E Tests > Inactive Client Behavior > should allow reactivating client and all contacts/users together ↓ Clients API E2E Tests > Permissions > should enforce read permissions for listing ↓ Clients API E2E Tests > Permissions > should enforce create permissions ✓ packages/scheduling/src/lib/tests/capacityThresholdWorkflowEvents.test.ts (3 tests) 1ms 697 MB heap used ee/temporal-workflows/src/activities/tests/portal-domain-reconcile.integration.test.ts (2 tests | 2 failed) 1ms 701 MB heap used × applyPortalDomainResources > routes virtual service traffic to the app once certificate succeeds 0ms → Missing "./admin.js" specifier in "@alga-psa/db" package × applyPortalDomainResources > creates new manifests and prunes legacy virtual services when the domain changes 0ms → Missing "./admin.js" specifier in "@alga-psa/db" package ✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 356ms 88 MB heap used server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 8 failed) 54ms 278 MB heap used ✓ EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 30ms × EE Chat (streaming state) > aborts the streaming request when Stop is clicked 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > Alga    <div class="message-content" > 

 Hello 

     <div class="message-feedback message-feedback--assistant" > <div class="feedback-container" > <div class="thumbs-container" />      <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
    × EE Chat (streaming state) > stops updating token display and ends generation state after Stop 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_25" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_26" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... × EE Chat (streaming state) > shows a streaming cursor while receiving tokens 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_25" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_26" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_27" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_28" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_29" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... × EE Chat (streaming state) > removes the streaming cursor when done is received 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_25" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_26" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_27" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... × EE Chat (streaming state) > shows the partial response when a network error occurs mid-stream 4ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > Alga    <div class="message-content" > 

 Hello 

     <div class="message-feedback message-feedback--assistant" > <div class="feedback-container" > <div class="thumbs-container" />      <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
    × EE Chat (streaming state) > shows an interruption indicator when the stream ends without done=true 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > Alga    <div class="message-content" > 

 Hello 

     <div class="message-feedback message-feedback--assistant" > <div class="feedback-container" > <div class="thumbs-container" />      <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="m-auto justify-center flex items-center text-center" style="min-height: 300px;" > <div class="initial-alga" > <h1 class="mt-6 text-2xl mx-1" > I am Alga! Your favorite AI assistant. Ask me a question.  
    <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
    × EE Chat (streaming state) > persists the assistant message after streaming completes 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_25" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... × EE Chat (streaming state) > persists assistant content matching the final streamed tokens 3ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_25" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_26" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_27" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_28" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... ✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 1ms 248 MB heap used ✓ server/src/test/unit/QuickAskOverlay.streaming.test.tsx (1 test) 21ms 261 MB heap used server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 6 failed) 3054ms 254 MB heap used ✓ ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 9ms × ExperimentalFeaturesSettings > defaults AI Assistant toggle to off 3ms → expected 'true' to be 'false' // Object.is equality × ExperimentalFeaturesSettings > renders experimental features warning banner 1005ms → Found multiple elements with the text: Experimental

Here are the matching elements:

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

Ignored nodes: comments, script, style <h5 class="mb-1 font-medium leading-none tracking-tight" > Experimental 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m...

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... × ExperimentalFeaturesSettings > calls updateExperimentalFeatures() with current toggle states on save 1009ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m...

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... × ExperimentalFeaturesSettings > shows success feedback after saving 1008ms → Found multiple elements with the role "button" and name "Save"

Here are the matching elements:

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

Ignored nodes: comments, script, style <button class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group" disabled="" type="button" > Save 

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m...

Ignored nodes: comments, script, style <body style="" > 

 <div class="rt-reset rt-BaseCard rt-Card rt-r-size-2 rt-variant-surface" > <div class="rt-Box rt-r-p-4" > <div class="flex justify-between items-center mb-4" > <h3 class="rt-Heading rt-r-size-4" > Contracts  
 
 
 Templates | Client Contracts | Drafts 
 
 <div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between" > <div class="relative max-w-md w-full" > <svg aria-hidden="true" class="lucide lucide-search absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" />  <div class="mb-0" > <input aria-label="Search draft contracts" class="w-full py-2 px-3 h-10 border rounded-md shadow-sm focus:outline-none focus:ring-2 placeholder:text-[rgb(var(--color-text-400))] border-[rgb(var(--color-border-400))] focus:ring-[rgb(var(--color-primary-500))] focus:border-transparent file:mr-3 file:rounded-md file:border-0 file:bg-[rgba(var(--color-primary-500),0.08)] file:px-3 file:py-2 file:text-sm file:font-medium file:text-[rgb(var(--color-primary-700))] pl-10" placeholder="Search drafts..." type="text" value="" /> 
 
  <div class="py-8 text-center text-gray-600" > No draft contracts. Start creating a new contract to save as draft.       
 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar m... ✓ ExperimentalFeaturesSettings > updates local state when toggled 4ms ✓ ExperimentalFeaturesSettings > loads current settings on mount 3ms × ExperimentalFeaturesSettings > renders list of features with toggles 9ms → expected [ <button …(8)>…(1), …(9) ] to have a length of 2 but got 10 × ExperimentalFeaturesSettings > disables AI Assistant toggle when not allowed 4ms → expected 'true' to be 'false' // Object.is equality ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests) 131ms 291 MB heap used server/src/test/unit/RightSidebar.streaming.test.tsx (1 test | 1 failed) 1007ms 289 MB heap used × RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 1007ms → Found multiple elements with the placeholder text of: Send a message

Here are the matching elements:

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_22" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_23" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_24" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_25" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_26" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_27" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_28" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_29" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2a" placeholder="Send a message" rows="3" style="height: 0px;" />

Ignored nodes: comments, script, style <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_2c" placeholder="Send a message" rows="3" style="height: 0px;" />

(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).

Ignored nodes: comments, script, style <body style="" > 

 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
  <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > Alga    <div class="message-content" > 

 Hello 

     <div class="message-feedback message-feedback--assistant" > <div class="feedback-container" > <div class="thumbs-container" />      <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > ...

Ignored nodes: comments, script, style <body style="" > 

 <div class="chat-container" > <div class="chats" > <div class="mb-auto w-full" > <div class="message-wrapper message-wrapper--user" > <div class="message-row message-row--user" > <div class="message-body message-body--user" > <div class="message-bubble message-bubble--user" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > You  
 
 <div class="message-content" > 

 Ping 

   <div aria-hidden="true" class="message-avatar message-avatar--user" > <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width: 60%; height: 60%;" viewBox="0 0 24 24" > <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> <circle cx="12" cy="7" r="4" />     <div class="message-feedback message-feedback--user" />  <div class="message-wrapper message-wrapper--assistant" > <div class="message-row message-row--assistant" > <div class="message-body" > <div class="message-avatar message-avatar--assistant" /> <div class="message-bubble message-bubble--assistant" > <div class="message-header" > <div class="message-header__left" > <span class="message-author" > Alga    <div class="message-content" > 

 Hello 

     <div class="message-feedback message-feedback--assistant" > <div class="feedback-container" > <div class="thumbs-container" />      <footer class="chat-footer" > <div class="chat-footer__inner" > <div class="chat-footer__input" > <textarea aria-busy="false" aria-label="Message Alga" class="chat-input" data-automation-id="chat-input" id="r_21" placeholder="Send a message" rows="3" style="height: 0px;" /> <p class="chat-input__hint" > Press Ctrl+Enter or ⌘+Enter to send. 

  <button class="chat-action chat-action--send" type="submit" > SEND    
 
 <p class="text-sm text-gray-700" /> 
 
 <button id="chat-empty-message-dialog-ok" > OK  
 
   
 <div class="chat-container" > ... ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.constraintHighlights.test.tsx (2 tests) 22ms 296 MB heap used ✓ packages/projects/tests/projectInfoDrawer.test.tsx (1 test) 27ms 322 MB heap used stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 2ms 294 MB heap used ✓ server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests) 112ms 312 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

✓ packages/billing/src/components/invoice-designer/DesignerShell.constraints.test.tsx (23 tests) 599ms 210 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 14ms 226 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1

stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }

stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' } iframeBridge: posting apiproxy_response { requestId: 'req-123', targetOrigin: '*' }

ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 3 failed) 139ms 242 MB heap used × Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 57ms → expected "spy" to be called with arguments: [ StringContaining{…}, …(1) ]

Number of calls: 0

✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 56ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 2ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 24ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 30ms 267 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 14ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:

✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 205ms 265 MB heap used ✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 149ms 280 MB heap used ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1232ms 360 MB heap used ✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 951ms 365 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 309ms ✓ EmailLogsClient > updates results when recipient search changes 304ms ✓ EmailLogsClient > updates results when ticket filter changes 307ms ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1537ms 262 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 314ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 624ms

Test Files 527 failed | 74 passed (601) Tests 138 failed | 456 passed | 271 skipped | 1 todo (866) Start at 14:54:45 Duration 25.80s (transform 2.37s, setup 314ms, collect 3.11s, tests 14.90s, environment 233ms, prepare 53ms) (pass).

2026-02-12 — T021 implemented

  • Added InvoiceTemplateEditor compiler-cutover wiring test to enforce save-path removal of extractInvoiceDesignerIr.
  • Evidence: packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts.

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts (pass).

2026-02-12 — T022 implemented

  • Closed save-path regression guard for generateAssemblyScriptFromIr usage using the same editor compiler-cutover suite.
  • Evidence: packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts.

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts (pass).

2026-02-12 — T023 implemented

  • Marked type-contract coverage for canonical templateAst payloads without legacy compile assumptions as implemented.
  • Evidence: packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T024 implemented

  • Marked tenant template save-path AST persistence wiring as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts::uses direct metadata persistence without AssemblyScript compile gating

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T025 implemented

  • Marked tenant template fetch/select AST payload wiring as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts::includes templateAst in template fetch/select paths

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T026 implemented

  • Marked standard template AST loadability as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts + invoiceTemplateAstPersistenceWiring.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T027 implemented

  • Marked preview action AST validation+evaluator+renderer integration path as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::executes AST validation + evaluator + renderer path

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T028 implemented

  • Marked preview action regression guard against AssemblyScript compiler command path as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplateCompileParity.test.ts::keeps preview action on AST evaluate/render path only

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T029 implemented

  • Marked preview action regression guard against Wasm executor references as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplateCompileParity.test.ts + invoiceTemplatePreview.integration.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).

2026-02-12 — T030 implemented

  • Marked sample-source preview continuity after AST pipeline swap as implemented.
  • Evidence: packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx::updates sample scenario selection while in Sample source mode

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T031 implemented

  • Marked existing-invoice preview continuity after AST pipeline swap as implemented.
  • Evidence: packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx::loads selected existing invoice detail and maps it for preview

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T032 implemented

  • Marked shape/render/verify status UI mapping coverage as implemented.
  • Evidence: packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts + previewStatus.test.ts + DesignerVisualWorkspace.test.tsx

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T033 implemented

  • Marked structured AST validation error surfacing in preview as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::surfaces structured schema diagnostics

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T034 implemented

  • Marked structured evaluator/strategy error surfacing in preview as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::surfaces structured evaluator diagnostics + rejects non-allowlisted strategy ids

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T035 implemented

  • Marked invoice PDF path shared AST evaluator/renderer helper wiring as implemented.
  • Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::uses shared AST evaluator and renderer helpers

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T036 implemented

  • Marked PDF invoice path regression guard against executeWasmTemplate usage as implemented.
  • Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::no longer depends on wasm execution helpers

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T037 implemented

  • Marked preview/PDF semantic parity integration coverage as implemented.
  • Evidence: packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T038 implemented

  • Marked preview compile cache removal and unreferenced wiring as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T039 implemented

  • Marked deleted compiler/executor files absence and import graph guard as implemented.
  • Evidence: packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T040 implemented

  • Marked post-cutover build/test viability without AssemblyScript compile helper module as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplateCompileParity.test.ts + invoiceLegacyCompilerRemoval.test.ts + passing suite

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T041 implemented

  • Added explicit save-path regression guard test ensuring AST template saves do not invoke compileAndSaveTemplate.
  • Evidence: packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts.

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts (pass).

2026-02-12 — T042 implemented

  • Closed persistence/runtime Wasm artifact removal coverage using save/runtime regression guards.
  • Evidence: packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts (wasmBinary drop + no runtime Wasm requirement).

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts (pass).

2026-02-12 — T043 implemented

  • Marked runtime render path guard against dependency as implemented.
  • Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::keeps preview and PDF paths on evaluator/renderer modules

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T044 implemented

  • Marked compatibility behavior where legacy columns coexist but AST stays canonical as implemented.
  • Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::treats templateAst as canonical even when legacy columns exist

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T045 implemented

  • Marked runtime rejection of non-allowlisted strategy IDs as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::rejects non-allowlisted strategy ids at runtime

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).

2026-02-12 — T046 implemented

  • Marked unit coverage for explicit transform composition order semantics as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies transform composition in declared order

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T047 implemented

  • Marked unit coverage for empty/edge invoice-item arrays in grouping/totals paths as implemented.
  • Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::handles empty invoice-item collections for grouping and totals composition

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).

2026-02-12 — T048 implemented

  • Marked integration coverage for preview pipeline using AST sample fixtures as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).

2026-02-12 — T049 implemented

  • Marked integration coverage for preview pipeline with existing-invoice-style query payload mapping as implemented.
  • Evidence: packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).

2026-02-12 — T050 implemented

  • Marked integration coverage for PDF generation pipeline with AST template fixture as implemented.
  • Evidence: packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).

2026-02-12 — T051 implemented

  • Marked parity test coverage for totals value equivalence between preview and PDF paths as implemented.
  • Evidence: packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts (Grand Total assertion)

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).

2026-02-12 — T052 implemented

  • Marked parity test coverage for grouped line-item ordering equivalence between preview and PDF paths as implemented.
  • Evidence: packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts (Products/Services ordering assertion)

Verification:

  • 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).

2026-02-12 — T053 implemented

  • Added docs architecture regression tests to assert the billing invoice-template docs describe AST model, evaluator/renderer pipeline, and strategy allowlist mechanism.
  • Evidence: packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts.

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts (pass).

2026-02-12 — T054 implemented

  • Closed documentation removal-note coverage using docs architecture regression tests that assert compiler/Wasm deletion details are documented.
  • Evidence: packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts (removed modules + preview cache removal assertions).

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts (pass).

2026-02-12 — T055 implemented

  • Added end-to-end-style author flow integration test covering: design workspace preview -> AST save -> server/PDF render.
  • Evidence: packages/billing/src/actions/invoiceTemplateAuthorFlow.e2e.test.ts.

Verification:

  • NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAuthorFlow.e2e.test.ts (pass).