Skip to content

Logical Architecture

The logical architecture separates functional responsibilities from physical hosting. This follows the Arcadia method’s principle of keeping logical components independent from their deployment targets. Each module is aligned to a specific ontological domain from the ontology stack.

Each module owns a bounded set of data and operations, organized by ontological domain:

ModuleResponsibilityOntological DomainPrimary tables
Identity & SessionExtract staff identity from CF Access JWT; provide Principal (email, subject) to all downstream handlersCCO Agent identificationN/A (stateless)
PerformanceMeasurement data queries, objective specification CRUD, nominal classification computation, mart-serving endpointsIAO Measurement Data + Objective Specificationsperformance_measurement_dataset, objective_specification
TagsTag content entities, information entity collections, unclassified-tag discovery, tag analyticsIAO Information Content Entities + Collectionstag_content_entity, information_entity_collection, material_artifact
CombosCreative act reports CRUD, import/export, plan specifications, suggestion generation + accept-to-logIAO Reports + Plan Specifications + Suggestion ICEscreative_act_report, plan_specification, suggestion_content_entity
AssetsInformation content entity lifecycle, content hash deduplication, denotation relations, ingest statusIAO ICEs + denotation relationsinformation_content_entity, denotation_relation
CSV ExportsDocument artifact request lifecycle, generation job orchestration, download URL managementIAO Documents carried by IBEsdocument_artifact
Ingest & SyncShopify data sync orchestration, watermarks, procedure execution tracking, repeatable rebuild/mart refreshPKO ProcedureExecution — the entire pipeline as process chainprocedure_execution_*, commercial_transaction_record, transaction_participation_record, material_artifact, sales_measurement_dataset, performance_measurement_dataset
HealthHealth endpoint, procedure execution reporting, operational statusProcedureExecution status observationprocedure_execution_record

REST-style endpoints for CRUD and dashboard queries. All staff-only, protected by CF Access:

GET /api/performance-metrics → list with filters (Measurement Data retrieval)
POST /api/performance-metrics/sync → enqueue sync job (ProcedureExecution initiation)
GET /api/combo-logs → list with filters (Creative Act Report retrieval)
POST /api/combo-logs/import → enqueue CSV import (ProcedureExecution)
POST /api/assets/ingest → enqueue asset ingest (ProcedureExecution)
POST /api/csv/generate → enqueue CSV export (Document Artifact generation)
GET /api/health → service + DB status (EngineeredSystem status)

Full endpoint inventory in Scenarios Overview.

Queue messages representing async work. Each message has a job_type discriminator typed as a PKO ProcedureExecution initiation:

Job typeProducerConsumerScenario
PROCEDURE_EXECUTION_INITIATECron / APIIngest WorkerBulk Sync
PROCEDURE_EXECUTION_POLLIngest WorkerIngest WorkerBulk Sync (16s interval, 128 max)
FULL_BACKFILL_EXECUTEAPI (manual)Ingest WorkerFull Backfill
ARTIFACT_TAG_SYNCAPIIngest WorkerTag Sync
ICE_INGESTAPIIngest WorkerAsset Ingest
DOCUMENT_ARTIFACT_GENERATEAPIIngest WorkerCSV Export
SUGGESTION_ICE_GENERATEAPIIngest WorkerCombo Suggestions
CREATIVE_ACT_REPORT_IMPORTAPIIngest WorkerCombo CRUD
MEASUREMENT_DATASET_REFRESHCron / Ingest WorkerIngest WorkerPipeline

Stable DTOs for API responses and queue payloads. Defined as Zod schemas shared between Workers, with field names matching the ontological naming conventions:

// Shared between dashboard-api and ingest workers
const IngestJobSchema = z.discriminatedUnion('job_type', [
z.object({
job_type: z.literal('PROCEDURE_EXECUTION_INITIATE'),
run_id: z.string().uuid(),
}),
z.object({
job_type: z.literal('ICE_INGEST'),
artifact_identifier: z.string(), // MaterialArtifact being denoted
dropbox_url: z.string().url(),
}),
// ...
]);
// API response DTOs
interface ArtifactMeasurementDatum {
artifact_identifier: string;
product_name: string;
aggregate_measurement_value: number;
sales_last_30_days: number;
nominal_classification: string;
// ...
}

A single shared module replaces the 6 duplicated implementations. The Shopify client acts as a boundary between the external EngineeredSystem (Shopify Admin API) and BluntDashboard’s internal domain:

// Logical interface — physical implementation in integrations/shopify
interface ShopifyClient {
bulkQuery(query: string): Promise<BulkOperationResult>
pollBulkOperation(id: string): Promise<BulkOperationStatus>
getProducts(params: PaginationParams): AsyncIterable<ShopifyProduct>
updateMetafield(productId: string, namespace: string, key: string, value: string): Promise<void>
}

This client handles authentication (permanent token preferred, Client Credentials Grant fallback), rate limiting (leaky bucket), retry with backoff, and structured logging.