Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ jobs:
- name: Apply Prisma migrations
run: pnpm --dir apps/api exec prisma migrate deploy --config prisma.config.ts --schema prisma/schema.prisma

- name: Domain pack governance
run: pnpm verify:domain-packs

- name: Worker boundary check (no api imports)
run: |
if grep -rE 'from.*(@ba-helper/api|apps/api/)' apps/worker/src/; then
echo "BOUNDARY VIOLATION: worker must not import from apps/api"
exit 1
fi

- name: Lint
run: pnpm lint

Expand Down
29 changes: 21 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,36 @@ Read: ui-tech-stack.md, ui-design.md, css-ownership.md
For Prisma/state/API changes:
Update docs + contracts + tests before completion.

## Current Delivery Focus
## v0.1 Status: Foundation Complete

Work is currently focused on:
The following foundational capabilities are complete and should not be re-implemented:

```text
1. Scan pipeline atomicity and snapshot publication safety
2. Evidence quality scoring and weak/missing evidence detection
3. Impact precision evaluation packs
4. Review coverage gates
5. Report trust UX and provenance visibility
6. Snapshot drift/freshness and public beta hardening
✅ Scan pipeline atomicity and snapshot publication safety
✅ Evidence quality scoring and weak/missing evidence detection
✅ Impact precision evaluation packs
✅ Review coverage gates (deterministic gate IDs)
✅ Report trust UX and provenance visibility
✅ Snapshot drift/freshness and public beta hardening
✅ Worker/API boundary separation (AiModule, PrismaModule worker-local)
✅ Domain-pack governance in CI
✅ Typed worker error classification
```

Do not add new domains as the center of gravity. Domain packs are controlled
terminology/risk/QA hint layers. Evidence is the source of truth and human
review is the final authority.

## Post-v0.1 Backlog (Parking Lot — Do Not Implement Without Explicit Scope)

```text
- Extract infrastructure repository classes from apps/api to shared backend package
- Move RunScanJobUseCase, RunDocumentJobUseCase to @ba-helper/application
- Multi-tenant organizationId boundary
- Private repository OAuth integration
- Scanner maturity gates for non-NestJS frameworks
```

## Instruction Loading And Workflow

This file is the repository-level instruction source.
Expand Down
8 changes: 8 additions & 0 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ COPY apps/web/package.json apps/web/package.json
COPY packages/contracts/package.json packages/contracts/package.json
COPY packages/shared/package.json packages/shared/package.json
COPY packages/analyzer/package.json packages/analyzer/package.json
COPY packages/backend-runtime/package.json packages/backend-runtime/package.json
COPY packages/application/package.json packages/application/package.json
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store \
sh -c "pnpm config set store-dir /pnpm/store && if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile --ignore-scripts; else pnpm install --ignore-scripts; fi"

Expand All @@ -19,12 +21,16 @@ ENV CI=true
COPY --from=deps /app/node_modules /app/node_modules
COPY --from=deps /app/apps/api/node_modules /app/apps/api/node_modules
COPY --from=deps /app/packages/analyzer/node_modules /app/packages/analyzer/node_modules
COPY --from=deps /app/packages/backend-runtime/node_modules /app/packages/backend-runtime/node_modules
COPY --from=deps /app/packages/application/node_modules /app/packages/application/node_modules
COPY . .
WORKDIR /app/apps/api
RUN /app/apps/api/node_modules/.bin/prisma generate --schema /app/apps/api/prisma/schema.prisma
RUN /app/node_modules/.bin/tsc -p /app/packages/contracts/tsconfig.json \
&& /app/node_modules/.bin/tsc -p /app/packages/shared/tsconfig.json \
&& /app/node_modules/.bin/tsc -p /app/packages/analyzer/tsconfig.json \
&& /app/node_modules/.bin/tsc -p /app/packages/application/tsconfig.json \
&& /app/node_modules/.bin/tsc -p /app/packages/backend-runtime/tsconfig.json \
&& /app/node_modules/.bin/tsc -p /app/apps/api/tsconfig.build.json

FROM base AS runtime
Expand All @@ -35,6 +41,8 @@ WORKDIR /app
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/apps/api/node_modules /app/apps/api/node_modules
COPY --from=build /app/packages/analyzer/node_modules /app/packages/analyzer/node_modules
COPY --from=build /app/packages/backend-runtime/node_modules /app/packages/backend-runtime/node_modules
COPY --from=build /app/packages/application/node_modules /app/packages/application/node_modules
COPY --from=build /app/apps/api/prisma /app/apps/api/prisma
COPY --from=build /app/apps/api/prisma.config.ts /app/apps/api/prisma.config.ts
COPY --from=build /app/packages /app/packages
Expand Down
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@anthropic-ai/sdk": "^0.99.0",
"@ba-helper/analyzer": "workspace:*",
"@ba-helper/application": "workspace:*",
"@ba-helper/backend-runtime": "workspace:*",
"@ba-helper/contracts": "workspace:*",
"@google/generative-ai": "^0.24.1",
"@nestjs/bullmq": "11.0.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ WHERE "metadata" ? 'selectedDomainPack';
-- Backfill multi-repo runs from the first child analysis. v1 creates child
-- analyses with the same explicit run-level selection when a run-level pack is
-- requested; mixed or legacy runs retain conservative defaults.
UPDATE "MultiRepoAnalysisRun" AS run
UPDATE "MultiRepoAnalysisRun"
SET
"requestedDomainPackId" = child."requestedDomainPackId",
"resolvedDomainPackId" = child."resolvedDomainPackId",
Expand All @@ -62,22 +62,22 @@ SET
"domainPackResolvedAt" = child."domainPackResolvedAt",
"domainPackManifestDigest" = child."domainPackManifestDigest",
"domainPackRegistryVersion" = child."domainPackRegistryVersion"
FROM LATERAL (
SELECT
analysis."requestedDomainPackId",
analysis."resolvedDomainPackId",
analysis."resolvedDomainPackVersion",
analysis."resolvedDomainPackStatus",
analysis."domainPackSelectedBy",
analysis."domainPackResolvedAt",
analysis."domainPackManifestDigest",
analysis."domainPackRegistryVersion"
FROM "ImpactAnalysis" AS analysis
WHERE analysis."multiRepoRunId" = run."id"
ORDER BY analysis."createdAt" ASC
LIMIT 1
FROM (
SELECT DISTINCT ON ("multiRepoRunId")
"multiRepoRunId",
"requestedDomainPackId",
"resolvedDomainPackId",
"resolvedDomainPackVersion",
"resolvedDomainPackStatus",
"domainPackSelectedBy",
"domainPackResolvedAt",
"domainPackManifestDigest",
"domainPackRegistryVersion"
FROM "ImpactAnalysis"
ORDER BY "multiRepoRunId", "createdAt" ASC
) AS child
WHERE child."resolvedDomainPackId" IS NOT NULL;
WHERE "MultiRepoAnalysisRun"."id" = child."multiRepoRunId"
AND child."resolvedDomainPackId" IS NOT NULL;

-- CreateIndex
CREATE INDEX "ImpactAnalysis_resolvedDomainPackId_resolvedDomainPackVersion_idx"
Expand Down
38 changes: 38 additions & 0 deletions apps/api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ enum DocumentType {
enum DocumentStatus {
DRAFT
APPROVED
/// @description STALE is a projection-only state derived at runtime. It is never persisted to the database.
STALE
}

Expand All @@ -157,6 +158,12 @@ enum DocumentJobStatus {
FAILED
}

enum LocalizationStatus {
QUEUED
COMPLETED
FAILED
}

enum ClarificationStatus {
OPEN
ANSWERED
Expand Down Expand Up @@ -678,11 +685,42 @@ model GeneratedDocument {
updatedAt DateTime @updatedAt
reviewedSnapshots ReviewedReportSnapshot[]
documentJobs DocumentJob[]
localizedArtifacts LocalizedReportArtifact[]

@@unique([impactAnalysisId, type, status])
@@index([impactAnalysisId, status])
}

model LocalizedReportArtifact {
id String @id @default(uuid())
sourceDocumentId String
sourceDocument GeneratedDocument @relation(fields: [sourceDocumentId], references: [id], onDelete: Cascade)

locale String // BCP-47 locale tag, e.g. "vi-VN"
sourceLocale String @default("en")
localizationStatus LocalizationStatus

contentMarkdown String?
sourceContentHash String // Computed from canonical JSON serialization

// Metadata for tracing and debugging
glossaryVersion String?
provider String?
model String?
translationPromptVersion String?
structuralValidatorVersion String?
fieldPolicyVersion String?

errorCode String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@unique([sourceDocumentId, locale])
@@index([sourceDocumentId])
@@index([locale])
@@index([localizationStatus])
}

model DocumentJob {
id String @id @default(uuid())
analysisId String @map("analysis_id")
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { QueueModule } from './modules/queue/queue.module';
import { AiModule } from './modules/ai/ai.module';
import { SystemModule } from './modules/system/system.module';
import { ClarificationModule } from './modules/clarification/clarification.module';
import { ApiLocalizationModule } from './modules/localization/localization.module';

import { AuthModule } from './modules/auth/auth.module';
import { JwtAuthGuard } from './modules/auth/application/jwt-auth.guard';
Expand All @@ -42,6 +43,7 @@ import { PublicBetaRateLimitPolicy } from './shared/rate-limit/public-beta-rate-
QueueModule,
SystemModule,
ClarificationModule,
ApiLocalizationModule,
AiModule.forRoot(),
],
providers: [
Expand Down
Loading
Loading