Observability, Structured Logging & Distributed Auditing
The GERCIA Platform enforces an enterprise Dual-Channel Observability & Auditing Architecture designed for high-throughput multi-tenant operations, strict regulatory compliance (LGPD & CFM Res. 1.821/2007), and zero database overhead.
flowchart TD
subgraph App ["GERCIA Ecosystem (.NET 10 Hosts & Edge)"]
Server["Gercia.Server (REST / STS / MCP)"]
Migrator["gercia-migrator (Cloud Run Job)"]
Edge["Gercia.Edge (Scale / Print Hardware)"]
end
subgraph Channel1 ["Channel 1: Serilog & Cloud Logging Pipeline (Zero DB Overhead)"]
direction TB
LogContext["LogContext Ambient Enrichment<br>(TenantId, UserId, TraceId)"]
StdOut["Structured JSON stdout<br>(RenderedCompactJsonFormatter)"]
GCP_LOGS["Google Cloud Logging<br>(Managed Ingestion & Logs Explorer)"]
GCP_BUCKET["Cloud Logging Log Bucket<br>(_Default / Regional Managed Storage)"]
Server & Migrator & Edge --> LogContext
LogContext --> StdOut
StdOut -->|"Native Container Ingestion"| GCP_LOGS
GCP_LOGS -->|"Managed Ingestion"| GCP_BUCKET
end
subgraph Channel2 ["Channel 2: Relational Audit Diff (PostgreSQL)"]
direction TB
EF["GerciaDbContext (Unit of Work)"]
AuditTable["core.audit_history Table<br>(Transactional Diffs on [Audit])"]
AdminUI["In-App Audit Trail UI<br>(Patient / Formula History)"]
Server & Migrator -->|"[Audit] SaveChangesAsync()"| EF
EF -->|"Atomic ACID INSERT"| AuditTable
AuditTable --> AdminUI
end
1. Dual-Channel Logging Strategy
Section titled “1. Dual-Channel Logging Strategy”The platform segregates telemetry into two decoupled, high-performance channels:
| Channel | Storage Target | Format | Retention & Purpose |
|---|---|---|---|
| Channel 1: Operational & Access Logs (Cloud Logging Pipeline) | Google Cloud Logging | Compact NDJSON (RenderedCompactJsonFormatter) |
Cloud Logging real-time indexing & managed retention. Containers write compact JSON to stdout, ingested natively by Google Cloud Logging for instant querying, log explorer dashboards, and automated alert policies. Zero impact on PostgreSQL. |
| Channel 2: Relational State Diffs | PostgreSQL core.audit_history |
Relational Rows (ACID) | Permanent active storage. Captures property-level before/after diffs for domain entities annotated with [Audit]. Consumed directly by in-app audit screens. |
2. Universal Ambient Context (LogContext)
Section titled “2. Universal Ambient Context (LogContext)”The platform leverages Serilog’s LogContext over .NET’s AsyncLocal<T> runtime execution context. This ambient context stamps 100% of log entries across async threads without polluting domain service signatures.
Universal Envelope Properties
Section titled “Universal Envelope Properties”Every generated JSON log event carries standard telemetry fields:
@t: RFC 3339 UTC timestamp (DateTimeOffset).@l: Log level (Information,Warning,Error,Fatal).@mt: Standardized Message Template.TenantId: Primary UUID of the active clinic, pharmacy, or enterprise tenant.BranchId: UUID of the specific branch workstation.UserId: UUID of the authenticated actor.TraceId&SpanId: Distributed W3C correlation IDs linking frontend SPA actions (@gercia/app), backend API requests, and Edge hardware jobs.Application: Service identity (Gercia.Server,gercia-migrator,Gercia.Edge).Environment: Deployment tier (Production,Staging,Development).
3. Standardized Message Templates (@mt)
Section titled “3. Standardized Message Templates (@mt)”Log message templates are strictly categorized using the CATEGORY | Action {Parameters} standard, powered by compile-time C# [LoggerMessage] Source Generators for zero memory allocation:
{ "@t": "2026-09-03T10:40:41.100Z", "@mt": "SCALE | Raw material {RawMaterial} weighed on scale {ScaleId}: {ActualWeight} g", "@l": "Information", "TenantId": "01918a32-7f2e-7000-8000-000000000099", "BranchId": "01918a32-7f2e-7000-8000-000000000088", "UserId": "01918a32-7f2e-7000-8000-000000000077", "TraceId": "4bf92f3577b34da6a3ce929d0e0e4736", "Application": "Gercia.Edge", "ScaleModel": "ToledoPrix3", "RawMaterial": "Minoxidil 5%", "TargetWeight": 50.00, "ActualWeight": 50.02, "WithinTolerance": true}Standard Prefix Categories
Section titled “Standard Prefix Categories”HTTP | ...: REST API request routing and execution latency.AUTH | ...: OpenIddict STS token issuance, social logins, and station token verification.CLINICAL | ...: Electronic medical records, patient diagnoses, and digital prescriptions.PHARMACY | ...: Compounding formulas, batch manufacturing orders, and stock operations.SCALE | ...: Serial scale calibration and monitored raw material weighings.PRINT | ...: Thermal label dispatch to ESC/POS or ZPL hardware.WORKER | ...: Background daemon cron schedules and async message processing.ERROR | ...: Handled business exceptions and unhandled system faults.
4. Universal Domain Attributes: [Audit] & [Encrypted]
Section titled “4. Universal Domain Attributes: [Audit] & [Encrypted]”The domain layer enforces clean declarative rules using two focused C# attributes:
namespace Gercia.Clinical.Patients;
[Audit]public class Patient : AggregateRoot, IMustHaveTenant{ public string FullName { get; private set; }
[Encrypted] public string Cpf { get; private set; }}Attribute Specifications
Section titled “Attribute Specifications”[Audit](Universal Auditing Marker):- On Entities: Tells
GerciaDbContextto track property diffs (OldValuevsNewValue) intocore.audit_history. - On Methods / Handlers: Tells application pipelines to publish structured access events (
EventType: "PhiAccess").
- On Entities: Tells
[Encrypted](Column-Level Cryptography):- Placed on sensitive string properties (
Cpf, medical notes). - Enforces transparent AES-256-GCM encryption at rest on PostgreSQL via
EncryptedConverter.
- Placed on sensitive string properties (
5. LGPD, CFM, ANVISA & Pediatric Long-term Archival (Google Cloud Storage)
Section titled “5. LGPD, CFM, ANVISA & Pediatric Long-term Archival (Google Cloud Storage)”For maximum legal protection and compliance with LGPD (Art. 37/46), CFM Resolution 1.821/2007, and ANVISA RDC 67/2007, GERCIA enforces audit custody across managed log retention and sovereign document storage in southamerica-east1 (São Paulo).
The Pediatric Legal Rationale (40 Years)
Section titled “The Pediatric Legal Rationale (40 Years)”Under Brazilian Civil Law (Civil Code, Art. 198, I), the statute of limitations for civil liability and medical claims does not run against minors (incapazes) until they reach the age of legal majority (18 years old).
- For a newborn or pediatric patient (0 years old), legal liability claims can be initiated up to 20 years after turning 18.
- Retaining medical records, digital prescriptions, and clinical attachments for up to 40 years (18 years until majority + 20-year CFM retention period + 2-year safety margin) guarantees 100% lifetime forensic protection for Doctors, Clinics, and Compounding Pharmacies.
Managed Cloud Logging vs. Sovereign Document Repositories
Section titled “Managed Cloud Logging vs. Sovereign Document Repositories”Following the decommissioning of redundant raw log sink buckets (gs://gercia-audit-logs and gs://gercia-staging-logs), operational logs and sovereign clinical attachments follow separated, specialized lifecycles:
| Storage Layer | Environment | Purpose | Retention & Lifecycle Strategy |
|---|---|---|---|
Google Cloud Logging (_Default Bucket) |
Production & Staging | Container operational stdout, request traces, error spikes, and health probes. | Managed Log Retention (Configurable retention period; zero maintenance overhead; integrated Logs Explorer). |
PostgreSQL core.audit_history |
Production | ACID state diffs for domain entities marked with [Audit]. |
Permanent Relational Storage (Synchronous replication, automated daily snapshots, and WAL archiving for PITR). |
gs://gercia-documents-prd |
Production | Clinical attachments, medical exams, compounding master sheets, and signed prescriptions. | 5-Rule FinOps Lifecycle (Standard ➔ Nearline 30d ➔ Coldline 90d ➔ Archive 365d; Soft Delete: Disabled; Retention Lock: Disabled). |
gs://gercia-documents-stg |
Staging | Integration testing attachments, sample prescriptions, and staging uploads. | 5-Rule FinOps Lifecycle (Standard ➔ Nearline 30d ➔ Coldline 90d ➔ Archive 365d; Soft Delete: Disabled; Retention Lock: Disabled). |
FinOps Storage Tiering & 5 Object Lifecycle Rules (gs://gercia-documents-{prd,stg})
Section titled “FinOps Storage Tiering & 5 Object Lifecycle Rules (gs://gercia-documents-{prd,stg})”Retaining clinical documents and attachments for decades under the Standard storage tier would incur unnecessary operational expense. To reconcile strict statutory durability with maximum cost efficiency (FinOps), the sovereign document repositories enforce a progressive 5-stage lifecycle transition policy:
flowchart LR
S0["1. Standard<br>(Day 0 - 30)<br>Active Clinical Access & Rapid Retrieval"]
S1["2. Nearline<br>(Day 30 - 90)<br>Infrequent Access (~50% Cost Cut)"]
S2["3. Coldline<br>(Day 90 - 365)<br>Rare Access (~80% Cost Cut)"]
S3["4. Archive<br>(Day 365 - Statutory)<br>Long-Term Custody (~94% Cost Cut)"]
S0 -- "Age ≥ 30 Days" --> S1
S1 -- "Age ≥ 90 Days" --> S2
S2 -- "Age ≥ 365 Days" --> S3
Official GCS Lifecycle Rules Matrix
Section titled “Official GCS Lifecycle Rules Matrix”| Rule # | Lifecycle Action | Target Condition | Precondition Filter | FinOps & Architecture Rationale |
|---|---|---|---|---|
| 1 | Delete Object | Noncurrent object with 3+ newer versions | Object Versioning enabled | Version Bloat Prevention: Restricts disk bloat by retaining at most 3 noncurrent versions when files are superseded. |
| 2 | Delete Object | 7+ days since object became noncurrent | Object Versioning enabled | Temporary Version Purge: Automatically cleans up superseded versions after 7 days, maintaining zero redundant storage overhead. |
| 3 | Set to Nearline | 30+ days since creation | Storage class matches Standard |
Recent Access Optimization: Documents older than 30 days transition to Nearline, cutting storage costs in half while keeping access latency in milliseconds. |
| 4 | Set to Coldline | 90+ days since creation | Storage class matches Nearline |
Quarterly Archival: Files older than 1 quarter transition to Coldline, reducing costs by ~80% compared to Standard tier. |
| 5 | Set to Archive | 365+ days since creation | Storage class matches Coldline |
Long-Term Forensic Custody: Archived records older than 1 year move to Archive tier, achieving ~94% cost savings for long-term statutory retention. |
Conflict Resolution & Evaluation Semantics
Section titled “Conflict Resolution & Evaluation Semantics”In compliance with Google Cloud Storage lifecycle evaluation precedence:
- Deletion overrides class transitions: If an object simultaneously satisfies an expiration/deletion condition and a storage class transition condition, the deletion action takes priority.
- More restrictive/cheaper storage classes take precedence: Transitioning to
Archivetakes precedence overColdlineorNearlineif an object qualifies for multiple class transitions at the same execution cycle.