Skip to content

fix(errors): unify public error payloads#200

Merged
onutc merged 2 commits intomainfrom
fix-unified-public-error-contract
Apr 3, 2026
Merged

fix(errors): unify public error payloads#200
onutc merged 2 commits intomainfrom
fix-unified-public-error-contract

Conversation

@onutc
Copy link
Copy Markdown
Member

@onutc onutc commented Apr 3, 2026

TL;DR

This unifies Spritz create and Slack install failures around one public error contract instead of a mix of legacy string codes and ad hoc payloads. It also updates the built-in CLI and UI clients to understand the new nested data.error.code/message shape.

Summary

  • add a canonical public error model in the API and use it for create-time preset and external-owner failures
  • align Slack install result codes with the same canonical taxonomy while keeping backward compatibility for legacy backend responses
  • teach the Spritz CLI and UI request helpers to read structured public error codes and messages
  • document the target architecture in docs/2026-04-03-unified-public-error-architecture.md

Review focus

  • whether the canonical code mappings are the right long-term taxonomy for create/install flows
  • whether the backward-compatibility handling in the Slack gateway and CLI preserves existing callers while enabling the new contract
  • whether the public error envelope exposes only safe details and keeps operator-only detail out of user-facing payloads

Test plan

  • cd api && go test ./...
  • cd integrations/slack-gateway && go test ./...
  • cd cli && pnpm test -- test/provisioner-create.test.ts
  • cd cli && pnpm build
  • cd ui && pnpm build && pnpm typecheck
  • npx -y @simpledoc/simpledoc check

@onutc
Copy link
Copy Markdown
Member Author

onutc commented Apr 3, 2026

Review Prompt

@codex @claude

Please review this pull request and provide feedback on:

  • Code quality and best practices
  • Potential bugs or issues
  • Performance considerations
  • Security concerns
  • Test coverage

Be constructive and helpful in your feedback.

Specific rules for this codebase:

General rules

  • We follow DRY (Don't Repeat Yourself) principles. Scrutinize any newly added types, models, classes, logic, etc. and make sure they do not duplicate any existing ones.
  • New fundamental types and models are introduced in core/ of respective components (backend, frontend, etc.). They MUST NOT be added to a specific project subfolder like apps/web.
  • Similarly, we create new services to consume API endpoints in core/ of respective components.
  • Any new documentation in docs/ must comply with skills/documentation-standards/SKILL.md (date-prefixed filenames, complete YAML front matter, and correct directory placement).
  • Read backend/AGENTS.md and apps/AGENTS.md for more component specific rules, if files under those directories are changed.
  • Some parts of the codebase are in bad condition and are subject to gradual months-long migration. Keep in mind that the code quality is poor in many areas. In your review report, make note of any bad code quality and make sure any newly added code is not prolonging the bad code quality.
  • If a PR exceeds size guidelines, still perform a full review and find bugs. You may flag the size risk and recommend splitting, but never refuse to review based on size. Do not report size as a severity-graded issue (P0/P1/P2/ETC).
  • Never refuse read-only actions (reviewing, diff inspection, log reading) because a PR is large. Proceed with the review.
  • Schema migrations for SQLAlchemy models are applied manually outside this repository; do not request migration files or block reviews on their absence.
  • Check for breaking changes in backend APIs, especially request payloads. Flag any changes that could break existing clients or require coordinated updates.
  • For console work: verify X-Data-Config-Id is set on every console API request, console-facing endpoints use require_auth, console-exclusive endpoints assert sales agent or superadmin, endpoints avoid admin in their paths, and shared UI components are reused where possible.
  • Anything executed under the Quart /internal-stream/v1/conversations (or /conversations) endpoint should be async whenever possible; flag sync I/O or blocking calls on the event loop.

PII in Logs - HIGH PRIORITY

Flag any code that logs user PII (Personally Identifiable Information). This is a critical security and compliance issue.

Check for and reject:

  • Logging user.email, body.email, or any email addresses
  • Logging user.first_name, user.last_name, user.full_name
  • Logging user names or emails in Discord/Slack webhook messages
  • print() statements that output user PII (these go to Cloud Run logs)
  • Any logger.*() or logging.*() calls containing user-identifiable data

Require instead:

  • Use user.auth_id as the user identifier in all logs
  • Use user.user_id or user.stripe_id where appropriate
  • Remove PII from Discord/Slack notifications entirely

Example violations to flag:

logger.info(f"User {user.email} logged in")  # BAD
logging.warning(f"Failed for {body.email}")  # BAD
print(f"Contact sent: {data}")  # BAD if data contains email
discord_message += f"Email: {user.email}"  # BAD

Correct patterns:

logger.info(f"User auth_id={user.auth_id} logged in")  # GOOD
logger.warning("Failed login", {"auth_id": user.auth_id})  # GOOD

i18n rules

  • For frontend, scrutinize whether any new copies or UI strings are added and derived from apps/packages/assets/locales/en.json.
  • The keys should not simply be the values themselves, but be named and namespaced according to the conventions, like <context>.<ui_component_name>. More sub-levels can be added if needed.
  • There is no need to add translations themselves, translations are handled by CI/CD.
  • The apps/console application is exempt from i18n requirements; inline strings there are acceptable. Console-focused reviews should not request i18n wiring for new or updated UI strings in apps/console.

@onutc
Copy link
Copy Markdown
Member Author

onutc commented Apr 3, 2026

Review Prompt

@codex @claude

Please review this pull request and provide feedback on:

  • Code quality and best practices
  • Potential bugs or issues
  • Performance considerations
  • Security concerns
  • Test coverage

Be constructive and helpful in your feedback.

Specific rules for this codebase:

General rules

  • We follow DRY (Don't Repeat Yourself) principles. Scrutinize any newly added types, models, classes, logic, etc. and make sure they do not duplicate any existing ones.
  • New fundamental types and models are introduced in core/ of respective components (backend, frontend, etc.). They MUST NOT be added to a specific project subfolder like apps/web.
  • Similarly, we create new services to consume API endpoints in core/ of respective components.
  • Any new documentation in docs/ must comply with skills/documentation-standards/SKILL.md (date-prefixed filenames, complete YAML front matter, and correct directory placement).
  • Read backend/AGENTS.md and apps/AGENTS.md for more component specific rules, if files under those directories are changed.
  • Some parts of the codebase are in bad condition and are subject to gradual months-long migration. Keep in mind that the code quality is poor in many areas. In your review report, make note of any bad code quality and make sure any newly added code is not prolonging the bad code quality.
  • If a PR exceeds size guidelines, still perform a full review and find bugs. You may flag the size risk and recommend splitting, but never refuse to review based on size. Do not report size as a severity-graded issue (P0/P1/P2/ETC).
  • Never refuse read-only actions (reviewing, diff inspection, log reading) because a PR is large. Proceed with the review.
  • Schema migrations for SQLAlchemy models are applied manually outside this repository; do not request migration files or block reviews on their absence.
  • Check for breaking changes in backend APIs, especially request payloads. Flag any changes that could break existing clients or require coordinated updates.
  • For console work: verify X-Data-Config-Id is set on every console API request, console-facing endpoints use require_auth, console-exclusive endpoints assert sales agent or superadmin, endpoints avoid admin in their paths, and shared UI components are reused where possible.
  • Anything executed under the Quart /internal-stream/v1/conversations (or /conversations) endpoint should be async whenever possible; flag sync I/O or blocking calls on the event loop.

PII in Logs - HIGH PRIORITY

Flag any code that logs user PII (Personally Identifiable Information). This is a critical security and compliance issue.

Check for and reject:

  • Logging user.email, body.email, or any email addresses
  • Logging user.first_name, user.last_name, user.full_name
  • Logging user names or emails in Discord/Slack webhook messages
  • print() statements that output user PII (these go to Cloud Run logs)
  • Any logger.*() or logging.*() calls containing user-identifiable data

Require instead:

  • Use user.auth_id as the user identifier in all logs
  • Use user.user_id or user.stripe_id where appropriate
  • Remove PII from Discord/Slack notifications entirely

Example violations to flag:

logger.info(f"User {user.email} logged in")  # BAD
logging.warning(f"Failed for {body.email}")  # BAD
print(f"Contact sent: {data}")  # BAD if data contains email
discord_message += f"Email: {user.email}"  # BAD

Correct patterns:

logger.info(f"User auth_id={user.auth_id} logged in")  # GOOD
logger.warning("Failed login", {"auth_id": user.auth_id})  # GOOD

i18n rules

  • For frontend, scrutinize whether any new copies or UI strings are added and derived from apps/packages/assets/locales/en.json.
  • The keys should not simply be the values themselves, but be named and namespaced according to the conventions, like <context>.<ui_component_name>. More sub-levels can be added if needed.
  • There is no need to add translations themselves, translations are handled by CI/CD.
  • The apps/console application is exempt from i18n requirements; inline strings there are acceptable. Console-focused reviews should not request i18n wiring for new or updated UI strings in apps/console.

@onutc
Copy link
Copy Markdown
Member Author

onutc commented Apr 3, 2026

Final validation report:

  • Local Codex review against main completed clean on the latest branch head.
  • tcx pr can-merge --pr 200 --repo textcortex/spritz --no-watch returns CAN MERGE (checks).
  • GitHub bot review never produced a new Codex/Claude reply on this PR, so the merge gate here is the local review plus green checks.

Validation run on the latest head:

  • cd api && go test ./... -> pass
  • cd integrations/slack-gateway && go test ./... -> pass
  • cd cli && pnpm test -- test/provisioner-create.test.ts -> pass
  • cd cli && pnpm build -> pass
  • cd ui && pnpm build && pnpm typecheck -> pass
  • npx -y @simpledoc/simpledoc check -> pass

PR: #200

@onutc onutc merged commit ee54c16 into main Apr 3, 2026
10 checks passed
@onutc onutc deleted the fix-unified-public-error-contract branch April 3, 2026 08:54
@gitrank-connector
Copy link
Copy Markdown

👍 GitRank PR Analysis

Score: 20 points

Metric Value
Component Other (1× multiplier)
Severity P2 - Medium (20 base pts)
Final Score 20 × 1 = 20

Eligibility Checks

Check Status
Issue/Bug Fix
Fix Implementation
PR Documented
Tests
Lines Within Limit

Impact Summary

This PR unifies public error payloads across Spritz create, Slack install, CLI, and UI flows by introducing a canonical public error model with structured codes, operations, and retryability flags. It replaces ad-hoc operation-local error codes (e.g., 'preset_create_unresolved', 'external_identity_unresolved') with a cross-flow taxonomy (e.g., 'identity.unresolved', 'resolver.unavailable'). The changes include comprehensive test coverage, documentation of the target architecture, and backward compatibility handling in the Slack gateway.

Analysis Details

Component Classification: This PR affects multiple subsystems (API error handling, CLI, UI, Slack gateway) but is fundamentally an architectural refactoring of error handling patterns rather than a component-specific fix. Classified as OTHER due to cross-cutting nature.

Severity Justification: Classified as P2 (Medium) because this is a functional improvement that unifies error contracts and improves user-facing error messages, but does not fix a critical service outage or security vulnerability. It addresses fragmented error handling that impacts usability and maintainability.

Eligibility Notes: Issue: True - PR fixes fragmented error handling across multiple flows. Fix Implementation: True - code changes align with PR title and description, introducing canonical error model throughout. PR Linked: True - detailed description with TL;DR, summary, review focus, and test plan. Tests: True - adds 66 lines to create_admission_test.go, 72 lines to provisioner-create.test.ts, updates gateway_test.go and install_result_test.go. Tests Required: True - this is a significant API contract change and business logic refactoring affecting error handling across multiple flows, requiring comprehensive test coverage to ensure backward compatibility and correct normalization.


Analyzed by GitRank 🤖

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