Skip to content

feat(api): retire solutions surface; delete Web3 Assurance code#45

Open
petterlindstrom79 wants to merge 1 commit into
mainfrom
feat/retire-solutions-and-web3-assurance
Open

feat(api): retire solutions surface; delete Web3 Assurance code#45
petterlindstrom79 wants to merge 1 commit into
mainfrom
feat/retire-solutions-and-web3-assurance

Conversation

@petterlindstrom79
Copy link
Copy Markdown
Member

Summary

Per DEC-20260503-A (dual-domain architecture: strale.dev = atomic capabilities, strale.io = bundled products) and chat 2026-05-04 (Web3 Assurance code deletion confirmed):

  • Solutions public surface retired — 4 routes return 410 Gone with structured deprecation body; 5 public-enumeration surfaces no longer mention solutions; 115 solution rows + 892 solution_steps rows archived and truncated.
  • Web3 Assurance code deletedapps/api/src/web3-assurance/ directory removed; MCP tool unregistered; SDK module deleted (Python SDK bumped to 0.2.0 → PyPI republish needed); routes unregistered.
  • Composition tech preservedlib/solution-executor.ts, lib/gate4b-solution-dryrun.ts, validateSolution() in onboarding-gates.ts kept for any future bundled-product module (Counterparty Assurance, when it ships).

Customer impact: zero. Pre-flight 2026-05-04 confirms no new external paying users since the prior investigation, web3-counterparty-dd has zero traffic ever, and the 4 callers on solutions (claude-test@strale.io, test@example.com, kshitij.mandloi@gmail.com, anonymous x402 vitalik.eth) are all attributable to Strale-internal or known-partner activity.

Files

Layer 1 — Solutions retirement (12 files)

  • routes/solutions.ts, routes/solution-execute.ts — 410 handlers
  • routes/x402-gateway-v2.ts — solution exec → 410, catalog/well-known/openapi pruned, _solCache + executeSolution import removed
  • routes/capabilities.ts:142–173part_of_solutions removed
  • routes/a2a.ts:115–177 — solution skills + product-web3-assurance skill removed
  • routes/llms-txt.ts:48–82 — solution list + Web3 Assurance prose pruned
  • lib/suggest.ts — solution catalog loader, +3 typeahead bonus, +0.03 semantic bonus, country-variant dedupe, reverse-index partOfSolutions, LLM solution prompt all removed
  • db/seed-solutions.ts — deleted
  • scripts/console-allowlist.json — seed-solutions entry removed
  • drizzle/0061_retire_solutions.sql + scripts/apply-migrations.ts block — archive + truncate

Layer 2 — Web3 Assurance deletion (~30 files deleted, 4 modified)

  • apps/api/src/web3-assurance/ — entire directory deleted (composer, types, evaluators, methodology, middlewares, data, lib)
  • app.ts — 5 imports + 5 route registrations removed
  • routes/mcp-server-card.ts — products list cleaned
  • openapi.ts/v1/web3-assurance path removed
  • packages/mcp-server/src/tools.tsstrale_web3_assurance MCP tool removed (~87 lines)
  • packages/sdk-python/straleio/web3_assurance.py — deleted
  • packages/sdk-python/straleio/__init__.py — export removed; version bumped 0.1.1 → 0.2.0

Verification

  • tsc --noEmit clean
  • vitest run — 390 pass, 4 skipped, 0 fail (was 425 — drop is from deleting web3-assurance/composer.test.ts and routes/solution-execute.test.ts which tested deleted code)
  • Linters: lint:no-bare-catch, lint:no-new-console, lint:migration-prefixes all clean
  • Pre-flight DB: 0 new external paying users since 2026-05-04; web3-counterparty-dd has 0 traffic ever; 115 solutions + 892 solution_steps rows ready to archive.
  • grep -ri "web3-assurance|web3_assurance|web3Assurance" apps/api/src/ returns zero matches.
  • Apply migration on production (Railway auto-runs apply-migrations.ts on deploy; will create solutions_archived_2026_05_04 + solution_steps_archived_2026_05_04 and truncate live tables)
  • PyPI republish straleio 0.2.0 (out of scope for this PR; flagged for follow-up)

Phase 1b follow-up (separate to-do)

Routes currently return 410 Gone but registrations remain. Next-release task:

  • Remove routes/solutions.ts, routes/solution-execute.ts, the x402 solutions handler entirely
  • Remove app.route("/v1/solutions", ...) registrations
  • Drop the empty solutions and solution_steps schemas (and the archive tables, if desired)
  • Wait at least 30 days from this PR's merge before scheduling

Tracked separately in Notion to-do DB.

Frontend impact

Current Lovable strale.dev shows solutions cards. After this lands, those cards will get 410 from the API and render broken/empty. Acceptable interim — Lovable is being replaced by the website rebuild.

Reverting

Database: INSERT INTO solutions SELECT (cols) FROM solutions_archived_2026_05_04; plus same for solution_steps. Code: git revert <sha>.

🤖 Generated with Claude Code

Per DEC-20260503-A (dual-domain architecture: strale.dev = atomic
capabilities, strale.io = bundled products) and chat 2026-05-04
(Web3 Assurance code deletion confirmed):

Layer 1 — Solutions public retirement:
- 4 public solutions routes return 410 Gone with structured
  deprecation body (full handler removal deferred to phase 1b):
  GET /v1/solutions, GET /v1/solutions/:slug,
  POST /v1/solutions/:slug/execute, GET|POST /x402/solutions/:slug
- 5 public-enumeration surfaces no longer surface solutions:
  routes/capabilities.ts (part_of_solutions removed from :slug),
  routes/a2a.ts (solution skills + product-web3-assurance skill removed),
  routes/llms-txt.ts (Web3 solution list + Web3 Assurance prose pruned),
  routes/x402-gateway-v2.ts (solutions removed from /x402/catalog,
  /.well-known/x402.json, OpenAPI paths; _solCache + executeSolution
  import removed),
  lib/suggest.ts (solution catalog loader, +3 typeahead bonus, +0.03
  semantic bonus, dedupe-country-variant block, LLM solution prompt,
  reverse-index partOfSolutions, all removed)
- Migration 0061 archives 115 solutions rows + 892 solution_steps rows
  to solutions_archived_2026_05_04 + solution_steps_archived_2026_05_04
  then truncates the live tables. Schemas retained for internal admin
  routes. Idempotent via apply-migrations.ts.
- Solutions seed file (db/seed-solutions.ts) deleted along with its
  console-allowlist entry.
- mcp-server-card.ts: products list cleaned (Payee Assurance and
  Web3 Assurance entries replaced with single Counterparty Assurance
  pointer that uses the existing strale_execute path).

Layer 2 — Web3 Assurance code deletion:
- apps/api/src/web3-assurance/ directory deleted entirely (~25 files)
- POST /v1/web3-assurance + 4 methodology endpoints unregistered from
  app.ts; imports removed
- packages/mcp-server/src/tools.ts: strale_web3_assurance MCP tool
  unregistered (~87 lines removed)
- packages/sdk-python/straleio/web3_assurance.py deleted; __init__.py
  export removed; SDK bumped to 0.2.0 (will need PyPI republish)
- openapi.ts /v1/web3-assurance path entry removed

Customer impact: zero. Pre-flight 2026-05-04 confirms:
- Same 23 paid solution calls all-time, 4 distinct callers
  (claude-test@strale.io, test@example.com, kshitij.mandloi@gmail.com,
  anonymous x402 vitalik.eth) — all attributable to Strale-internal or
  known-partner activity per chat investigation.
- Zero new external paying users since 2026-05-04.
- Zero web3-counterparty-dd traffic ever (any status, all-time).

Counterparty Assurance is being built as a fresh module separately
(placeholder to-do filed). Composition / dispatch / audit-logging tech
preserved (lib/solution-executor.ts, lib/gate4b-solution-dryrun.ts,
validateSolution() in onboarding-gates.ts) for potential CPA reuse.

Phase 1b (full route handler removal in next release) tracked as a
separate to-do.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
petterlindstrom79 added a commit that referenced this pull request May 4, 2026
…ites (#49)

Per the 2026-05-04 paid-vendor audit + DEC-20260504-A audit-followup
test coverage protocol. Stops the hourly-cadence bleed on Dilisense,
eSortcode, and Anthropic Sonnet calls that PR #46 inadvertently
amplified by moving the scheduler from 24h to 1h cadence.

Scope (intentionally tight — verified ground-truth via executor source):

- pep-check, sanctions-check, adverse-media-check (Dilisense): 2-char
  name guard then unconditional fetch to api.dilisense.com per call.
  No free-probe path; no input bypass. Every scheduled run = 1 paid
  Dilisense call. → external_cost_cents = 1.
- uk-cop-check (eSortcode Pay.UK): the manifest currently passes
  test_outcome=MATCHED which eSortcode burns no credits for, but the
  classification is still wrong as a flag. Future test-input change
  could start burning credits unexpectedly. → external_cost_cents = 1
  per the user's future-proofing instruction.
- risk-narrative-generate: Sonnet 4.6 (DEFAULT_MODEL constant in the
  executor), max_tokens 1500. Conservative cost upper bound: 4K input
  × $3/MTok + 1500 output × $15/MTok ≈ $0.034 ≈ €0.031. Round up to
  3 cents so the scheduler skips it (any non-zero value excludes from
  hourly cadence) and the cost reflects real magnitude. →
  external_cost_cents = 3.

Filter (idempotent + scope-bounded):
- active = true
- test_mode = 'live' (skip 'fixture' = saved data; skip 'canary' =
  existing non-zero values preserved)
- test_type IN ('known_answer', 'edge_case', 'negative', 'known_bad')
- external_cost_cents = 0 (preserve existing manual values)

Excludes by design (zero-cost-by-design test types):
- schema_check (dry-run mode, no API call)
- dependency_health (zero-cost auth-less probe per CLAUDE.md
  Principle A — skipAuth: true on probe means a 401 proves
  connectivity without consuming quota)
- piggyback (not scheduled; populated by customer traffic)

Expected updated rows: 22 (16 Dilisense/eSortcode at 1¢ + 6
risk-narrative-generate at 3¢). Pre-flight verified against prod;
suite IDs in PR description.

NOT in scope (explicitly deferred per user instruction; separate
to-dos):

- Anthropic-Haiku bulk set (~80 caps): per-call cost depends on
  input/output token volume; flat 1-cent gives misleading false
  safety signal. Defer to a separate PR with proper per-call cost
  estimation (read max_tokens per executor + estimate typical
  input).
- Browserless suites (37 caps): Browserless billing is per-minute,
  not per-call; mapping it onto external_cost_cents requires a
  different model.
- Capability-level misclassifications (~8-12 caps tagged
  maintenance_class = 'commercial-stable-api' but actually free):
  Companies House, AviationStack free tier, RVO/Kadaster,
  Arbetsförmedlingen, CommonCrawl. Fix the maintenance_class
  classification on the capability, not the suite cost. Separate
  to-do.

Migration shape: drizzle/0062_paid_vendor_suite_cost.sql + idempotent
runtime block in scripts/apply-migrations.ts. Number gap from 0059 to
0062 leaves 0060 + 0061 free for the open feat/marketplace-eligible-
flag (PR #42) and feat/retire-solutions-and-web3-assurance (PR #45)
branches; the migration-prefix lint catches collisions either way.

Post-condition assertion baked into both the SQL migration (DO $$
RAISE EXCEPTION on remaining_zero > 0) and the apply-migrations.ts
block (logs remaining-at-zero count). If a new paid-vendor suite
landed at cost=0 between audit and apply, the assertion fails with
a clear message rather than letting the suite quietly bleed.

Tests: 3 new in src/jobs/paid-vendor-suite-cost.test.ts. Compiles the
UPDATE SQL via PgDialect.sqlToQuery and asserts:
- Slug whitelist (4 + 1) is exact; bystander slugs are absent
- test_mode = 'live' filter present; fixture/canary excluded
- known_answer/edge_case/negative/known_bad included; schema_check/
  dependency_health/piggyback excluded
- external_cost_cents = 0 idempotency guard present
- scope-sanity test pins the in-scope slug set so a scope-creep
  edit (e.g. adding ~80 Anthropic-Haiku slugs) trips a test
  failure instead of silently shipping

Verification:
- tsc --noEmit clean
- vitest run — 450 pass, 11 skipped, 0 fail (3 new regression tests)
- lint:no-bare-catch / lint:no-new-console / lint:migration-prefixes
  all clean (62 migrations, no prefix collisions)
- 22 rows verified pre-flight against prod (suite IDs listed in PR
  description)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant