E2E Test Report -- pdf-engine

E2E Test Report – pdf-engine

Report ID: TEST-20260409-PDF Date: 2026-04-09 Service: pdf-engine (ods-platform) Operator: ADLC Pipeline (automated) + manual validation Session: First E2E after 9-day outage (BUG-003 recovery)


1. Executive Summary

Metric Value
Total tests executed 12
Passed 10
Failed 1
Blocked 1
Pass rate 83%
Bugs found 1 (BUG-004, severity HIGH)
Service status RECOVERED – operational after 9-day outage
Verdict PASS_WITH_NOTES

pdf-engine is back online after the BUG-003 outage (2026-03-31 to 2026-04-09). Core functionality is healthy: template CRUD, job creation, authentication, and multi-tenant isolation all pass. One new bug discovered: BUG-004 – duplicate template names are accepted (HTTP 201) when the spec requires HTTP 409 Conflict. One test was blocked due to a test script crash unrelated to the service.

Critical Finding

BUG-004: Duplicate template name returns 201 instead of 409. The database unique index uq_templates_tenant_name_active exists but the Rust handler does not catch the PostgreSQL error code 23505 (unique_violation). This is a data integrity issue that allows ambiguous template names per tenant.


2. Test Environment

Parameter Value
Staging URL https://pdf-engine.staging.orbusdigital.com
Stack Rust / Actix-web / PostgreSQL 17 (schema: pdf)
Auth method OID RS256 JWT (Bearer token)
Auth provider https://oid.staging.orbusdigital.com
Database PostgreSQL 17, schema pdf, migrations up to 007
Previous session 2026-04-01 (TC-PDF-002 BLOCKED due to HS256/RS256 mismatch)
Comparison First full CRUD test session since 2026-03-26 automated run

3. Test Results

ID Test Name HTTP Verdict Notes
TC-PDF-001 Health Check 200 PASS /health returns 200 with service metadata
TC-PDF-002 Unauthenticated -> 401 401 PASS Request without Bearer token correctly rejected
TC-PDF-003 List Templates 200 PASS Returns array for authenticated tenant
TC-PDF-004 Create Template 201 PASS Happy path, all fields returned
TC-PDF-005 Get Template 200 PASS Retrieved by UUID, correct tenant scoping
TC-PDF-006 Update Template 200 PASS PATCH updates body_html
TC-PDF-007 Duplicate Name -> 409 201 FAIL BUG-004: Expected 409, got 201. See section 4.
TC-PDF-008 List Jobs 200 PASS Returns array for authenticated tenant
TC-PDF-009 Create Job 201 PASS Job created with status pending
TC-PDF-010 Get Job BLOCKED job_id not captured due to test script crash
TC-PDF-011 Delete Template 204 PASS Soft delete confirmed (GET after returns 404)
TC-PDF-012 Cross-Tenant Isolation 200 PASS Tenant B cannot access Tenant A resources

Result Breakdown


4. BUG-004: Duplicate Template Name Accepted

Summary

Field Value
Bug ID BUG-004
Severity HIGH
Status OPEN
Test case TC-PDF-007
Discovered 2026-04-09
Category Data integrity / Error handling

Description

When creating a template with a name that already exists for the same tenant, the API returns HTTP 201 (Created) and inserts a duplicate row. The spec requires HTTP 409 (Conflict).

Reproduction Steps

  1. Authenticate with a valid OID JWT for tenant A.
  2. Create a template: POST /v1/templates with {"name": "E2E-Final-113903", "content_type": "html", "body_html": "<p>original</p>"} – returns 201.
  3. Create the same template again: POST /v1/templates with {"name": "E2E-Final-113903", "content_type": "html", "body_html": "<p>dup</p>"} – returns 201 (expected: 409).
  4. Two templates now exist with the same name for the same tenant.

Expected vs Actual

Aspect Expected Actual
HTTP status 409 Conflict 201 Created
Response body {"error": "conflict", "message": "Template with this name already exists"} New template object with different ID
Database Insert rejected by unique index Second row inserted

Root Cause

The database unique index uq_templates_tenant_name_active ON pdf.templates (tenant_id, name) WHERE deleted_at IS NULL exists in the schema. However, the create_template handler in src/api/templates.rs does not match on sqlx::Error::Database with error code 23505 (unique_violation). The constraint error is either swallowed by a generic error handler or mapped to HTTP 500, which then gets caught as a different path.

Impact

In the create_template handler, catch the PostgreSQL unique violation:

Err(sqlx::Error::Database(e)) if e.code() == Some(Cow::Borrowed("23505")) => {
    HttpResponse::Conflict().json(json!({
        "error": "conflict",
        "message": "Template with this name already exists"
    }))
}

Estimated effort: ~10 lines across src/api/templates.rs and src/repository/template_repo.rs.

Historical Context

This bug was previously identified as BUG-002 in the automated E2E suite run on 2026-03-26 (scenarios TPL-VAL-09 and TPL-VAL-10 failed with the same symptom: status 201 instead of 409). It was not prioritized during the BUG-003 outage recovery. The 2026-04-09 manual E2E session confirms the bug persists and has been reclassified as BUG-004 at HIGH severity.


5. Recovery Context: BUG-003 Outage

Timeline

Date Event
2026-03-31 pdf-engine stops responding on staging. Container exits with migration 007 panic.
2026-04-01 E2E session: TC-PDF-001 PASS (health), TC-PDF-002 BLOCKED (JWT auth fails, container running HS256 old build).
2026-04-07 BUG-003 diagnosed: sqlx ignores ?search_path=pdf in DATABASE_URL. Migrator reads wrong schema, panics on migration 007 (table already exists in public).
2026-04-07 Fix applied: explicit SET search_path = pdf via sqlx after_connect callback. PR#6 merged to staging.
2026-04-07 All 4 reviews completed: BA PASS, Architect PASS_WITH_NOTES, Security PASS, DevOps PASS_WITH_NOTES.
2026-04-09 Service redeployed and healthy. E2E session: 10/12 PASS (83%). BUG-004 discovered.

BUG-003 Resolution Summary

Lessons Learned

  1. PostgreSQL search_path must be set explicitly via after_connect, not via URL parameter, when using sqlx with schema isolation.
  2. Container healthcheck requires curl in the Docker image – missing curl caused Coolify healthcheck failures and masked the actual migration error.
  3. The is_preview env var must be set correctly for Coolify deployments to avoid incorrect build behavior.

6. Comparison with Previous Sessions

Metric 2026-03-26 (automated) 2026-04-01 (manual) 2026-04-09 (manual)
Total tests 69 2 12
Pass rate 68.1% (47/69) 50% (1/2) 83% (10/12)
Auth working Yes (HS256) No (HS256/RS256 mismatch) Yes (RS256)
Template CRUD Yes Not tested Yes
Job CRUD Partial Not tested Partial (1 blocked)
Multi-tenancy Yes (8/8) Not tested Yes (1/1)
Duplicate name bug Present (TPL-VAL-09) N/A Present (TC-PDF-007)
Service status Running Unhealthy Recovered

Key improvements since 2026-03-26: - Auth upgraded from HS256 to RS256 (aligned with OID) - BUG-003 (migration panic) resolved - CORS configuration fixed (was returning 400 on OPTIONS) - Container healthcheck operational

Remaining from 2026-03-26: - BUG-004 (duplicate name) still open - PDF manipulation endpoints (split, merge, rotate) still not implemented (P1+ scope) - FK violation error message not sanitized to spec wording


7. Blocked Test: TC-PDF-010

Field Value
Test TC-PDF-010: Get Job
Verdict BLOCKED
Reason Test script crashed before capturing the job_id from TC-PDF-009 response
Service impact None – this is a test infrastructure issue
Recommendation Fix the test script to properly capture and propagate the job_id variable between test cases

8. Recommendations

Immediate (before next E2E session)

  1. Fix BUG-004 – Add 23505 error code handling in create_template handler. Estimated 10 lines. This is a data integrity issue and should be resolved before any production promotion.

  2. Fix test script – TC-PDF-010 blocked due to variable propagation failure. Not a service bug but must be fixed for complete test coverage.

Short-term

  1. Rerun full 69-scenario automated suite – The last automated run was 2026-03-26 with 68.1% pass rate. Many failures were related to BUG-003 (now fixed) and test harness issues. A rerun will establish the true current baseline.

  2. Audit for duplicate templates – Query pdf.templates for any rows with duplicate (tenant_id, name) pairs created during the period when BUG-004 was active. Clean up if found.

  3. Enable Coolify healthcheck – DevOps review noted health_check_enabled=False. Must be corrected before production deployment.

Medium-term

  1. Implement PDF manipulation endpoints – Split, merge, rotate APIs are specified but not yet implemented (P1 scope). These accounted for most failures in the 2026-03-26 automated suite.

  2. Set container memory limits – DevOps review noted no memory limits configured in Coolify.


9. Evidence Locations

Path Contents
~/dev/ops/reviews/pdf-engine/e2e-report-20260409.json This session’s raw results (12 tests)
~/dev/ops/reviews/pdf-engine/bug-004-duplicate-template-name.json BUG-004 detailed finding
~/dev/ops/reviews/pdf-engine/e2e-report.json Previous automated run (69 tests, 2026-03-26)
~/dev/ops/test-evidence/2026-04-01-v2/TC-PDF-001/verdict.json Previous session health check evidence
~/dev/ops/test-evidence/2026-04-01-v2/TC-PDF-002/verdict.json Previous session auth block evidence

Report generated 2026-04-09 by documentarian agent. Next action: fix BUG-004, then rerun full automated E2E suite.