ScopeSpindle / trust

What the code can tell you about your bid package.

This page stays deliberately narrow: it describes visible application behavior for PDF uploads, saved reports, access checks, deletion, and analytics. It does not turn those observations into provider or infrastructure assurances.

Read the verified facts first, then the UNKNOWN register. If the code cannot establish something, ScopeSpindle does not claim it here.

01 / The short version

Evidence, storage, and limits.

The public flow returns a teaser without creating a saved report. The authenticated flow saves structured report data—not the original PDF binary—and scopes report operations to the signed-in owner.

Public teaser

Analyzed in memory, no report row created.

Saved report

Structured JSON and retained passages are stored.

Access

Report routes require auth and match the owner ID.

02 / The upload paths

Two flows. Different persistence.

Both paths validate one non-empty PDF up to 25 MB. The application behavior after that validation is different by design.

Public /api/free-analysis

A teaser, not a saved report
No row created

The browser base64-encodes the selected PDF and posts it to the public route. The route validates the file, reconstructs an in-memory File, and sends it for analysis.

The response is a teaser: decision and confidence, filename and project name when available, counts for risks, requirements, RFIs, and missing items, plus selected retained source passages for the refrigerant and HVAC risk lenses.

This route does not create a BidIntelligenceReport database row.

Authenticated /api/bid-recommendation

A saved, reviewable report
Owner scoped

After file validation and requireAuth(), the route sends the PDF bytes as a base64 PDF data URL to the configured AI proxy and validates the structured analysis.

It adds citation IDs and the professional-review disclaimer, then stores one report row keyed by the authenticated userId. The original PDF binary is not stored in the application report model.

A report-ready email contains the project, recommendation, confidence, and a link to the saved report. A failed email emits a warning; it does not change the saved report result.

03 / What is stored

A report record, not the source file.

The application database model stores the report output and its evidence structure. It does not define a column for the uploaded PDF binary.

BidIntelligenceReport

Application database fields
userId
sourceFilename
report JSON
processingStatus
createdAt
updatedAt

The JSON can contain the recommendation and confidence; reasons; summary, project, and deadline fields; eight named report sections and their claims; citations; refrigerant and HVAC risk checks; suggested RFIs; the disclaimer; and up to 24 verbatim source passages. Each retained passage includes document filename, page, and text capped at 1,200 characters.

04 / Application deletion

Delete the saved row.

The delete route is application-level and owner-scoped. It is precise about what it removes and deliberately silent about systems the route cannot inspect.

DELETE /api/bid-reports/[id]

What success means

After requireAuth(), the route calls deleteMany with both the report ID and authenticated userId. A successful deletion removes that saved report row, including its JSON and retained source passages, from the application database.

Application deletion makes no claim about provider logs, backups, AI systems, email copies, caches, or infrastructure deletion.

05 / Access and analytics

The visible control points.

These are concrete application paths, not a generalized security or compliance claim.

Owner-scoped report access
  • Report reads

    The report index and detail GET look up records with the authenticated user ID. A report from another owner is returned as not found.

  • Report actions

    Authenticated upload, QA, suggested RFIs, PDF export, and deletion paths call requireAuth(). Creation records the authenticated user ID.

  • Boundary of the claim

    This is a report-route access observation, not a platform-wide tenant-isolation or infrastructure-controls claim.

First-party analytics

What the code records

App analytics posts an allowlisted event to /api/analytics/events. TheAnalyticsEvent row contains event name, timestamp, optional authenticated user ID, a local-storage visitor ID, route, and bounded metadata.

Funnel events are best-effort. The free flow records upload-started, completed, and abandoned events; the authenticated detail route records report views. Separately, the framework conditionally emits a page-load beacon to its configured platform base when POLSIA_ANALYTICS_SLUG is present.

Visible warnings and errors include failed report-ready email delivery and startup seed diagnostics. No report or PDF content logging is established in the reviewed application paths.

UNKNOWN / do not infer

What this code review cannot establish.

An absent application code path is not proof that an infrastructure behavior is absent. These boundaries stay explicit until separately verified.

Infrastructure providers and regions
UNKNOWN — these page-level application paths do not establish which providers or regions process or store data.
Provider retention or deletion
UNKNOWN — application deletion does not prove deletion from provider systems, logs, backups, or other infrastructure.
Encryption
UNKNOWN — this page does not infer encryption at rest, in transit, or within downstream services from the visible route code.
Downstream AI handling and training use
UNKNOWN — the configured AI proxy is visible, but provider retention, review, model handling, and training use are not established here.
Logs, caches, and backups
UNKNOWN — the code shows selected events and warnings, not the full behavior of operational logs, caches, or backups.
Personnel and subprocessors
UNKNOWN — no personnel access list or subprocessor assurance is claimed by this page.
Platform-wide tenant isolation
UNKNOWN — the verified claim is limited to user-scoped report routes, not every platform subsystem.
Upload boundary

Until handling is otherwise verified, upload only synthetic, public, redacted, non-confidential, or otherwise authorized material.

The authenticated app does not retain the original PDF binary in its report row. That does not make a promise about provider retention or other systems outside the visible application database.

The human-review boundary

A first pass is not approval.

ScopeSpindle’s result is an AI-generated first pass. A qualified estimator must verify scope, requirements, pricing, schedule, and commercial risk before a bid decision.