Infinite Cabinet
A field report on the InfiniteCabinet project — what it is, what we pull into REV.health, and what we leave behind. InfiniteCabinet is the upstream "jig" that produced REV.health's IC framework; this page makes the lineage explicit and books the remaining work.
What InfiniteCabinet is
InfiniteCabinet is a metadata-driven, template-generated, end-to-end
enterprise application builder. You hand it a JSON Application
Model Interface (AMI) describing a single business noun (an
Invoice, a Customer) plus a companion rules file, and
its code-generation engine produces a full stack: Cosmos / EF Core schema, .NET 9
minimal-API CRUD endpoints, Angular 21 standalone components packaged as Web
Components, validation middleware, OpenAPI spec, xUnit / Vitest tests, and
HTML docs — in a fixed pipeline of
DB → API → Components → Tests → Docs → Deploy.
Three pillars hold the model up: a numeric 0–100 RBAC engine with four
permission scopes; a strict version format
break.feature.bug.buildtimestamp with cascade deployment that
forbids prod from running ahead of lower envs; and a 14-rule "hard rules"
contract that the generator (not policy) enforces (OrgID on everything, soft
delete only, audit columns auto-injected, max 500 lines per file, API enforces
referential integrity because Cosmos has no FKs).
Why it matters to REV.health
REV.health's existing IC framework is already a re-skinned, clinical-aware fork of the InfiniteCabinet generator. Every module page in PRD v2 (clinical-doc, scheduling, rcm, …) implicitly assumes IC-style AMI generation. What is missing is the provenance: which patterns came directly from InfiniteCabinet, which we changed for HIPAA / FHIR / multi-org data sharing, and which we never adopted. This page closes that loop and captures the artifacts the v1 gap report flagged as P0 (per-module IC-application overrides, RBAC matrix per module, versioning worked examples). Anything ADOPT or ADAPT is a candidate copy/port job; anything INSPIRE or DROP needs a one-time decision and then stays decided.
The "Infinite Cabinet" jig
InfiniteCabinet treats application code the same way. The AMI schema is the workpiece (changes per app: Invoice today, Encounter tomorrow). The CodeGenerationOrchestrator + templates + hard rules are the jig: they hold the schema in place and machine it through a fixed sequence of cuts (DB → API → Frontend → Tests → Docs). Two operators feeding the same AMI to the same jig get byte-identical output, same audit columns, same OrgID partitioning, same RBAC hooks, same component tag names — because the generator, not the developer, enforces the invariants.
For REV.health that translation is straight: Encounter,
Appointment, Claim, PriorAuth,
Prescription, Referral are workpieces. The jig
guarantees that EncounterID is a Short GUID, that
OrganizationID partitions the container, that audit fields
are present, that the generated component is ic-ng21-clinical-doc-detail-encounter,
and that no junior developer can field-rename in prod without an EditAMI
(level 90) grant. Hand-written exceptions are still possible, but they are
visible: anything not produced by the jig stands out in code review.
Artifact inventory
Each row is one re-usable thing in InfiniteCabinet. Verdict is one of:
| Artifact | Source path | Concept | Verdict | Target REV.health module | Effort | Priority |
|---|---|---|---|---|---|---|
| AMI schema model | src/IC.Models/Ami/AmiSchema.csAmiEntity.cs, AmiField.cs, AmiFieldType.cs |
Top-level schema, entities, fields, FK metadata | ADAPT | Cross-cutting — data-model | M | P0 |
| AMI rules companion | src/IC.Models/Ami/AmiRule.cs |
Independently-versioned validation rules linked by version range | ADOPT | coding-cds, eligibility | S | P1 |
| BreakingChangeDetector | src/IC.Models/Ami/BreakingChangeDetector.cs |
Diffs two schema versions, classifies each change as breaking / feature | ADOPT | Cross-cutting — codegen tooling | S | P0 |
| AuditFieldInjector | src/IC.Models/Ami/AuditFieldInjector.cs |
Auto-adds OrgID, LastUpdatedDateTimeUTC, LastUpdatedByUserID, IsSoftDeletedBool to every entity |
ADAPT | Cross-cutting — data-model audit | S | P0 |
| CodeGenerationOrchestrator | src/IC.CodeGen/CodeGenerationOrchestrator.cs |
Orders phases DB → API → FE → Tests → Docs; path-traversal guards; max-lines-per-file check | ADOPT | Platform tooling | L | P0 |
| TemplateEngine | src/IC.CodeGen/TemplateEngine.cs |
Scriban/Handlebars-style template binding | ADOPT | Platform tooling | S | P1 |
| RBAC engine (PermissionGrant) | src/IC.Security/Models/PermissionGrant.csPermissionScope.cs, EffectivePermission.cs, PermissionLevel.cs |
Numeric 0–100 grants over (app, env, entity) with Object / Row / Column / ComplexAlgorithm scopes; hierarchical merge across User → Role → RoleGroup | ADAPT | Cross-cutting — ic-reference RBAC | L | P0 |
| RbacMiddleware + ResponseShapingMiddleware | src/IC.Api/Middleware/ |
Resolves EffectivePermission per request, strips Column-hidden fields from response | ADOPT | Platform — API gateway | M | P0 |
| DefaultOrgProvisioner | src/IC.Security/Services/ |
On org create: seed default roles (Admin, Editor, Viewer), groups, settings | ADAPT | Platform onboarding | M | P1 |
| L1 component library | libs/components/src/lib/l1/ (10 primitives) |
text-input, number-input, date-picker, currency-display, dropdown, boolean-toggle, textarea, guid-display, title, badge-status — all Shadow DOM Web Components | ADOPT | Cross-cutting — shared UI | M | P0 |
| L2 structured components | libs/components/src/lib/l2/ |
address-form, phone-input, email-input, file-upload, image-picker, rich-text-editor | ADAPT | Cross-cutting — need clinical extensions (allergy-picker, problem-search, sig-builder) | M | P1 |
| JTable grid | libs/components/src/lib/jtable/jtable.ts |
Standard grid: sortable, filterable, paged, ARIA-correct, Shadow DOM | ADOPT | All worklists (RCM denials, task inbox, prior-auth queue, scribe review) | S | P0 |
| ComponentMappingService | libs/components/src/lib/component-mapping.service.ts |
Type → component tag resolution table with custom overrides | ADOPT | Cross-cutting — ic-reference default bindings | S | P0 |
| WebComponentRegistry | libs/components/src/lib/web-component-registry.ts |
Lazy registration of ic-* tags on first DOM appearance via import map |
ADOPT | Shell / patient-portal / clinician shell | M | P1 |
| AMI Editor (SSMS-style) | libs/ami-editor/ |
Visual schema editor: root noun far left, children flow left-to-right, FKs above PKs, breaking-change controls disabled below EditAMI | INSPIRE | Internal platform tooling (not customer-facing) | L | P2 |
| API Gateway (YARP) | src/IC.Gateway/ |
Reverse proxy on port 5472, route per app/env/version, session auth, rate limit, CORS | ADAPT | Platform — replace YARP with Azure API Management for SMART-on-FHIR launch context support | L | P1 |
| Hard rules (14) | rules/hard-rules.md |
Non-negotiable invariants enforced by generator: OrgID on everything, soft-delete only, version format, build-once-run-everywhere, … | ADOPT | Cross-cutting (with one carve-out, see below) | S | P0 |
| Naming conventions | rules/naming-conventions.md |
Tag format ic-{fw}{ver}-{scope}-{break}-{name}; field type suffixes InvoiceNumber200, IsActiveBool |
ADAPT | Already partially in ic-reference; needs the field-type-suffix rule added | S | P1 |
| Version format | rules/versioning.mdsrc/IC.Models/Ami/AmiVersion.cs |
break.feature.bug.buildtimestamp on every artifact; only break goes in component tag |
ADOPT | Cross-cutting | S | P0 |
| Cascade deployment rule | rules/hard-rules.md #6 |
Deploying to env X auto-promotes all envs left of X; prod always has lowest-or-equal version | ADOPT | Platform CI/CD — architecture | M | P1 |
| Blue-green DB strategy | rules/hard-rules.md #13context/decisions-log.md DEC-012 |
Breaking schema change creates new DB + ETL; old DB stays for rollback; never in-place migration | ADOPT | Cross-cutting Cosmos strategy | L | P1 |
| Component picker / FK auto-naming | context/decisions-log.md DEC-014 |
In editor, pick target noun first; system creates field {Noun}ID with FK metadata |
ADOPT | Internal AMI editor + codegen tooling | S | P2 |
| Apps-are-nouns rule | context/decisions-log.md DEC-003 |
One business noun = one app = one AMI; cross-noun via FK only | ADAPT | Already in ic-reference module nouns; surface as a hard rule | S | P0 |
| Sample AMIs (Bogus seeded) | data/ami/ (Invoice, Customer, Location, Product) |
Faker-seeded JSON; "one-button schema-to-hero demo" | INSPIRE | Need clinical equivalents: Patient, Encounter, Appointment, Claim, Prescription | M | P1 |
| Test scale (~1,869 tests) | tests/IC.Api.Tests/ + Vitest specs |
915 xUnit + 441 shell + 227 components + 286 ami-editor | INSPIRE | Sets the bar for REV.health module test coverage | — | P1 |
| Compodoc + HTML doc set | docs/ (architecture, api-reference, component-library, security, versioning, PRD) |
Auto-generated documentation per artifact | INSPIRE | This PRD v2 is the equivalent surface; doc-gen for generated components is P1 | M | P1 |
| JSON-file dev storage | data/ |
JSON files under data/{orgId}/… as Cosmos stand-in for local dev |
INSPIRE | Worth doing for local clinician shell dev; not for prod | S | P2 |
| NX monorepo layout | nx.json, apps/, libs/ |
NX 22.6.3 + pnpm workspaces, Angular 21 + .NET 9 side-by-side | INSPIRE | REV.health uses separate repos per module (DEC-RH style); NX stays a reference | — | P2 |
AMI schema model
source: src/IC.Models/Ami/AmiSchema.cs + AmiEntity.cs + AmiField.cs + AmiFieldType.cs
AmiSchema shape ADAPT
The top-level schema. One AMI per business noun. Inherits BaseEntity which gives Id, OrgId, LastUpdatedDateTimeUtc, LastUpdatedByUserId, IsSoftDeletedBool.
public class AmiSchema : BaseEntity
{
public string Name { get; set; } // "Invoice"
public string? Description { get; set; }
public string RootNoun { get; set; } // "Invoice" — apps are nouns
public string Version { get; set; } // "1.3.0.20260401120000"
public List<AmiEntity> Entities { get; set; }
public List<VersionHistoryEntry> VersionHistory { get; set; }
}
Adaptation for clinical: add SourceOrganizationID (nullable) for global entities (Patient, Problem, Diagnosis, Prescription — see data-model). Add FhirResourceType hint (Encounter, MedicationRequest) so the generator can emit a FHIR mapper alongside the CRUD endpoint.
AmiField shape ADOPT
public class AmiField
{
public string Name { get; set; }
public string Type { get; set; } // AmiFieldType constants
public bool Required { get; set; }
public bool IsPrimaryKey { get; set; }
public bool IsForeignKey { get; set; }
public string? FkTargetSchema { get; set; } // "Customer"
public string? FkTargetEntity { get; set; }
public string? ComponentMapping { get; set; } // override default tag
}
AmiFieldType constants ADAPT
Source list: String, Int, Decimal, Money, Bool, DateTime, Guid, Text, Email, Phone, Url. Clinical extensions needed (these become the bridge to ic-reference default bindings):
| New AMI type | Default REV component | Purpose |
|---|---|---|
ShortGuid | short-guid-display | 22-char Base62 PK — already in data-model |
Snomed | snomed-picker | SNOMED CT concept selector |
Icd10 | icd10-picker | ICD-10-CM diagnosis selector |
Cpt | cpt-picker | CPT/HCPCS procedure selector with 4 modifier slots |
RxNorm | rxnorm-picker | Medication name → RxCUI / NDC |
Loinc | loinc-picker | Lab observation code |
FhirReference | fhir-ref-input | Polymorphic { resourceType, id } reference |
Code generation orchestrator
source: src/IC.CodeGen/CodeGenerationOrchestrator.cs
Five-phase pipeline with strict ordering. Adopt the orchestrator skeleton verbatim, then swap in REV-specific templates per phase.
graph LR AMI["AMI schema
(+ optional Rules)"] --> P0["Phase 0
Parse & validate
path-safe names"] P0 --> P1["Phase 1
Database
(Cosmos / EF Core)"] P1 --> P2["Phase 2
API
(CRUD + Validation + OpenAPI)"] P2 --> P3["Phase 3
Frontend
(Grid / Form / Detail)"] P3 --> P4["Phase 4
Tests
(CRUD + Validation + Contract)"] P4 --> P5["Phase 5
Docs
(SchemaDoc + ApiDoc)"] P5 --> OUT["GenerationResult
+ 500-line check
+ path-traversal guard"]
Why adopt the skeleton: the orchestrator already enforces three things we want in every REV codegen run —
IsNameSafeForPath()rejects.., slashes, leading non-letters before writing anything (HIPAA-relevant: prevents tenant boundary escape via crafted entity names).IsPathUnderBase()resolves the absolute path and verifies it stays under the output dir — defence in depth.MaxLinesPerFilerejects any generated file over the rule-9 threshold (default 500). Forces template authors to split.
Integration sketch:
var orchestrator = new CodeGenerationOrchestrator(new CodeGenOptions
{
SelectedPhases = { GenerationPhase.Database, GenerationPhase.Api,
GenerationPhase.Frontend, GenerationPhase.Tests,
GenerationPhase.Docs },
MaxLinesPerFile = 500,
TemplateSet = "rev-health-v1" // REV-specific templates
});
var result = orchestrator.Generate(encounterSchema, encounterRules);
if (!result.Success) throw new CodeGenException(result.Errors);
CodeGenerationOrchestrator.WriteToDirectory(result, "out/clinical-doc/");
RBAC engine (0–100)
source: src/IC.Security/
The numeric scale — identical to the one already documented in ic-reference, but with InfiniteCabinet's two extra layers:
Permission levels ADOPT
public static class PermissionLevel
{
public const int NoAccess = 0;
public const int Read = 1;
public const int Write = 51;
public const int Deploy = 70;
public const int ManageFeatures = 80;
public const int EditAmi = 90;
public const int Admin = 100;
}
REV.health needs four more named levels in the middle — Clinical-Read (30), Clinical-Write (50), Administrative (70), Platform-Op (100) — matched to the existing IC reference table. The two ladders coexist by leaving the integer scale unchanged and adding more named constants.
Four scopes ADOPT
| Scope | What it controls | REV use case |
|---|---|---|
Object | Whole-entity access (most common) | "MA can read Appointment but not Claim" |
Row | Per-row filter expression on top of OrgID partition | "Provider sees only encounters where RenderingProviderID = self" |
Column | Hide specific fields below a threshold level | "Hide SsnLastFour from Reception (level 30); show to Billing (level 70)" |
ComplexAlgorithm | Custom function for break-the-glass / consent gates | Sensitive-class gating (42 CFR Part 2 SUD records, HIV, behavioral health) |
PermissionGrant shape ADAPT
public class PermissionGrant
{
public string AppName { get; set; } = "*"; // "scheduling", "rcm"
public string Environment { get; set; } = "*"; // "Dev", "QA", "UAT", "Prod"
public string EntityName { get; set; } = "*"; // "Appointment"
public string Scope { get; set; } // Object / Row / Column / ComplexAlgorithm
public int Level { get; set; } // 0–100
public bool Recursive { get; set; } = true;
public string TargetType { get; set; } = "RoleGroup"; // User | Role | RoleGroup
public string TargetId { get; set; }
// Column scope
public List<string>? RestrictedFields { get; set; }
public int? FieldVisibilityLevel { get; set; }
// Row scope
public string? RowFilterExpression { get; set; }
// ComplexAlgorithm scope
public string? AlgorithmId { get; set; }
public string? AlgorithmParameters { get; set; }
}
Clinical adaptations: add SensitiveClassRequirement (matches SensitiveClassGating in patient-portal); add ConsentTokenRequired bool for cross-org reads of global entities; rename OrgId → OrganizationID to match REV naming.
EffectivePermission resolver ADOPT
The middleware merges User → Role → RoleGroup grants (recursive), takes the max numeric level per scope, collects all HiddenFields from Column grants, all RowFilters from Row grants, and stores the result in HttpContext.Items for the rest of the request. ResponseShapingMiddleware then strips hidden fields from the JSON response body before send.
Reuse this as-is — it solves the Column-scope problem we already documented in data-model read-access audit.
L1 / L2 / JTable components
source: libs/components/src/lib/
InfiniteCabinet ships 17 ready Web Components, all ViewEncapsulation.ShadowDom, all mobile-first, all framework-agnostic at consumption time:
| Tier | Components (source tag prefix ic-ng21-core-1-) |
|---|---|
| L1 primitives (10) | text-input, number-input, boolean-toggle, date-picker, currency-display, dropdown, textarea, guid-display, title, badge-status |
| L2 structured (6) | address-form, phone-input, email-input, file-upload, image-picker, rich-text-editor |
| JTable (1) | Sortable, filterable, paged grid. ARIA roles, Shadow DOM, ~335 LOC, fully tested |
Default type-to-component mapping ADOPT
Verbatim from component-mapping.service.ts:
export const DEFAULT_COMPONENT_MAP: ComponentMapping = {
String: 'ic-ng21-core-1-text-input',
Text: 'ic-ng21-core-1-textarea',
Int: 'ic-ng21-core-1-number-input',
Decimal: 'ic-ng21-core-1-number-input',
Money: 'ic-ng21-core-1-currency-display',
Bool: 'ic-ng21-core-1-boolean-toggle',
DateTime: 'ic-ng21-core-1-date-picker',
GUID: 'ic-ng21-core-1-guid-display',
Enum: 'ic-ng21-core-1-dropdown',
Address: 'ic-ng21-core-1-address-form',
Phone: 'ic-ng21-core-1-phone-input',
Email: 'ic-ng21-core-1-email-input',
};
This is already partially documented in ic-reference default bindings; the inventory there lists 13 rows but the source has the same 13 plus the case-insensitive normalize + override mechanism. Port the service, not just the table.
Breaking-change detector
source: src/IC.Models/Ami/BreakingChangeDetector.cs
What counts as breaking ADOPT
| Change | Verdict | Required level |
|---|---|---|
| Add optional field | Feature bump | Write (51) |
| Add required field | Breaking | EditAMI (90) |
| Remove field | Breaking | EditAMI (90) |
| Change field type | Breaking | EditAMI (90) |
| Add entity | Feature bump | Write (51) |
| Remove entity | Breaking | EditAMI (90) |
| Rules-only change | Rules version bump | Write (51) |
The detector explicitly ignores the four audit fields (OrgID, LastUpdatedDateTimeUTC, LastUpdatedByUserID, IsSoftDeletedBool) when computing diffs. Adopt this filter and extend it with REV's audit set (CreatedDateTimeUTC, ModifiedDateTimeUTC, ModifiedByUserID, SourceOrganizationID).
Versioning & cascade deploy
source: rules/versioning.md + rules/hard-rules.md (rules 1, 6, 7, 8, 9)
Version format break.feature.bug.buildtimestamp ADOPT
Universal across schemas, components, APIs, rules, deployments, docs — never semver. The build timestamp is ISO-8601 UTC (e.g. 1.3.0.20260401120000) and is what makes every artifact uniquely traceable.
Only the break segment goes in the component tag (ic-ng21-core-1-text-input). Feature and bug updates ship the same tag with a different CDN URL. Consumers never need to update tag names for non-breaking changes.
Cascade deployment ADOPT
Deploying to env X auto-promotes Dev → QA → UAT → X. Prod always has the lowest-or-equal version. Combined with rule #8 ("no testing in prod") this is a structural rather than policy enforcement.
REV.health implication: the prod cascade rule replaces our current ad-hoc release notes. Worth picking up as a P1 CI/CD change.
Build-once-run-everywhere & cosmos blue-green ADOPT
Components are immutable env-agnostic bundles; only DI config differs per env (Cosmos URL, CDN tag). For schema-breaking DB changes, never migrate in place — create new Cosmos database, ETL, keep old DB live for rollback grace period. This pairs naturally with the version-pinning rule (rule #12: every CDN module requires explicit version).
Glossary & naming
source: rules/naming-conventions.md + glossary terms scattered across docs/ and context/
| Term | Meaning in InfiniteCabinet | REV.health equivalent |
|---|---|---|
| AMI | Application Model Interface — JSON schema for one app's data + relationships | Same term, same meaning; canonical noun for every schema page |
| Apps are nouns | One business noun = one app = one AMI = one repo | Module nouns: scheduling, clinical-doc, rcm, erx-epcs, … (see ic-reference module nouns) |
| Jig | (implicit) The codegen pipeline + hard rules that hold an AMI in place while machining | Same; this page introduces the term explicitly |
| BoxApps view | The SSMS-style schema editor visualisation where root noun is far left and children flow right with FKs above PKs | Internal AMI editor tooling — not customer-facing |
| Core bundle | All L1 + L2 + JTable shipped as one bundle.js CDN file (one HTTP call) | Adopt for clinician shell and patient portal |
| Trust tier | (absent from InfiniteCabinet) | REV.health-only concept — see clinical-doc scribe + v1 gap report |
| Scribe | (absent) | REV.health-only — ambient AI documentation flow |
| FK-as-component view | Editor mode where CustomerID renders as the linked entity ("Customer") with an arrow to the target | Worth importing into the data-model page diagrams |
| Short name toggle | Editor mode that displays InvoiceLineItem as LineItem when context is unambiguous | Apply to EncounterNote → Note in chart UIs |
| Field-type suffix convention | InvoiceNumber200 (max-len), IsActiveBool (positive bool only) | Not currently in REV naming — ADD to ic-reference |
Cross-module impact
What changes in each REV.health module if we land the ADOPT and ADAPT artifacts above:
| REV.health module | What lands here | What changes |
|---|---|---|
| data-model | AMI schema model, AuditFieldInjector, BreakingChangeDetector, ShortGuid + clinical types | Existing AMI tables get versioned via break.feature.bug.buildtimestamp; audit injector formalised; breaking-change checker added to CI |
| ic-reference | RBAC scopes (four), ComponentMappingService, naming conventions (field-type suffix), apps-are-nouns hard rule | Three new sections: "Four permission scopes", "Field type suffix convention", "Apps are nouns invariant" |
| architecture | CodeGenerationOrchestrator phase order, cascade deployment rule, build-once-run-everywhere, blue-green DB | New "Generation pipeline" diagram, env-cascade promotion rule formalised in CI |
| clinical-doc | JTable for scribe review queue, Row-scope grants for "rendering provider only", ComplexAlgorithm for 42 CFR Part 2 gating | EncounterNote sensitive-class fields covered by ColumnGrant; scribe inbox becomes a JTable instance |
| scheduling | JTable for slot/waitlist views, Row-scope filter for "resource = self", PermissionGrant per Schedule | Resource-graph and waitlist surfaces unified through one grid |
| rcm | JTable for denial queues, ClaimLine generation from CPT picker AMI type, Column grants on patient PHI for billing-only roles | Denial worklist becomes a paged JTable; PHI redacted by ResponseShapingMiddleware |
| eligibility | AMI Rules companion for Prior-Auth state machine, BreakingChangeDetector to gate plan-rule edits | Rules editor surfaces a "would break" warning before save |
| erx-epcs | RxNorm AMI type, ComplexAlgorithm scope for controlled-substance EPCS challenge | Prescription form binds RxNorm picker; EPCS verification routed through scope evaluator |
| patient-portal | Core bundle (L1+L2+JTable) on portal shell, address-form / phone-input / email-input for registration, SensitiveClassGating via ComplexAlgorithm | Portal registration form is generated from User AMI instead of hand-coded |
| coding-cds | SNOMED / ICD-10 / CPT AMI types, AMI Rules for CDS hooks, ComponentMappingService overrides per code system | CDS rule library uses Rules companion with independent versioning |
| task-mgmt | JTable for task inbox, Row-scope for "assigned to me" | Task macros become AMI Rules entries |
| referrals | Apps-are-nouns hard rule (referral is its own noun), JTable for referral inbox | Standing referral becomes its own AMI rather than a flag on Referral |
| payer-opt | AMI Rules for PayerRule, ComplexAlgorithm scope for optimization-suggestion gating | OptimizationAuditEntry written by ResponseShapingMiddleware shim |
Explicitly dropped (and why)
| Source artifact | Why dropped |
|---|---|
| NX monorepo layout (single repo for everything) | REV.health is committed to repo-per-module (DEC-RH style, surfaced in ic-reference project structure). NX stays a reference for tooling parallelism, not adopted wholesale. |
| JSON-file storage as dev backend | InfiniteCabinet uses data/{orgId}/*.json for local dev to avoid a Cosmos emulator. Useful pattern, but PHI-touching modules need a Cosmos emulator path anyway for fidelity. Marked INSPIRE, not DROP — kept for the small handful of seedable non-PHI catalogue entities (CodeSet, SpecialistDirectory). |
| YARP-based gateway | YARP is fine in isolation, but REV.health needs SMART-on-FHIR launch context, OAuth 2.1 with PKCE, and per-payer rate-limit policies. Azure API Management gives all three out of the box. The gateway responsibilities are adopted; the YARP implementation is not. |
| SSMS-style visual AMI editor | Internal-tools polish, not customer-facing. INSPIRE rather than ADOPT — we don't need to invest editor effort until non-engineer schema authoring is on the roadmap. |
| Compodoc-driven docs site | PRD v2 is the canonical doc surface. Generated-component reference docs from Compodoc are P1 worth doing but not a doc-site replacement. |
| Bogus-seeded sample AMIs (Invoice, Customer, Location, Product) | Wrong nouns for the clinical domain. We need clinical equivalents (Patient, Encounter, Appointment, Claim, Prescription) seeded with Bogus — same technique, different data. |
| One global env picker at shell level (Phase 1) | REV.health needs per-payer-context env selection (sandbox vs prod) for integrations work. Global picker doesn't model that. |
| Generic "Editor / Viewer / Admin" default roles | Replaced by REV's clinical role ladder (Patient, MA/Nurse/Reception, PA/NP/Physician, Practice Manager / RCM, IT Admin) on the same 0–100 scale. |
REV.health-built components (IC adoption candidates)
The following components were built for REV.health during the 2026-06-02 session and are structured to be lift-able into the Infinite Cabinet component library. They are not sourced from InfiniteCabinet but follow IC conventions (props-driven, single-purpose, CSS-token-only styling).
| Component | File | IC merge target | L1/L2 tier | Priority | Notes |
|---|---|---|---|---|---|
claim-timeline | demo/assets/claim-timeline.js | badge-status L1 + new L2 status-pipeline | L2 | P1 | Headline + full mode; status registry with long labels; per-node rendering merges with badge-status L1 primitive |
claim-drawer | demo/assets/claim-drawer.js | New L2 claim-detail-drawer | L2 | P2 | Right-side panel with header, timeline, action toolbar, history table; keyboard + backdrop dismiss |
patient-encounters | demo/assets/patient-encounters.js | New L2 encounter-generator | L2 | P2 | Deterministic synthetic encounter generator with AI summaries; bucketByMonth() and detectClusters() helpers |
fmtRelative | demo/assets/shared.js | New L1 relative-time | L1 | P0 | "5 mins ago" / "3 hours ago" / "2 days ago"; same shape as fmtHours |
providerDisplayName | demo/assets/shared.js | New L1 entity-name | L1 | P1 | Resolves provider ID → full display name with credential suffix |
fmtHours | demo/assets/dashboard.js | New L1 duration-display | L1 | P0 | "50 mins" / "1 hour" / "2.5 hours"; replaces "50m"/"1h" cryptic shorthand |
Phone Input (US/CA) | demo/assets/ic-phone-input.js | New L1 phone-input | L1 | ADOPT | Opt-in via data-ic-phone="US"|"CA" (both NANP). Live-formats (NNN) NNN-NNNN; on blur normalizes 10 digits to +1 (NNN) NNN-NNNN; exposes dataset.icPhoneDigits + dataset.icPhoneE164; setCustomValidity for HTML5 validation; idempotent initAllPhoneInputs(root) for dynamic re-renders |
Open questions for human review
- Permission level overlap. InfiniteCabinet defines Write=51, Deploy=70, ManageFeatures=80, EditAmi=90, Admin=100. ic-reference defines Patient=10, Clinical-Read=30, Clinical-Write=50, Administrative=70, System-Admin=90, Platform-Op=100. Need a single merged ladder — or an explicit decision that the two scales are namespaced (platform-ops vs clinical).
- Audit field naming. Source uses
OrgID,LastUpdatedDateTimeUTC,LastUpdatedByUserID,IsSoftDeletedBool. REV.health data-model usesOrganizationID,CreatedDateTimeUTC,ModifiedDateTimeUTC,ModifiedByUserID. Pick one; update AuditFieldInjector accordingly. - BaseEntity inheritance vs duck-typed audit. InfiniteCabinet uses class inheritance (
: BaseEntity). REV.health AMI is JSON-only and currently has no equivalent base type. Add a "$schema" reference or an explicit base AMI template? - FHIR mapping placement. Generate a FHIR resource mapper in Phase 2 (API) or as a separate Phase 6? Affects whether external systems can hit the generated FHIR endpoint directly.
- Rules companion lifecycle. InfiniteCabinet bumps rules independently. For payer/eligibility rule churn this is right. For Prior-Auth state machine changes that imply schema changes (new statuses), should the rules bump cascade-bump the schema?
- Tag prefix convention. Keep
ic-ng21-or switch torev-ng21-for clinical components? Affects every component tag REV.health ships. - Build-once-run-everywhere & PHI. Same component bytes in Dev and Prod is fine, but a Dev env that talks to Synthea fake data must never resolve to a Prod Cosmos DI config. Need stronger guarantees than "the import map is correct".
- Cascade deployment with regulatory holds. Cascade rule says deploying to UAT promotes Dev / QA automatically. What happens when prod is held back for ONC / EHNAC certification? Need an explicit "frozen prod" exception.
Cross-links
- IC Application Reference — the downstream surface that this page back-fills.
- Data Model — where the AMI schema, BaseEntity audit fields, and ShortGuid convention land.
- Encounter Type System — concrete example of an AMI schema that benefits from AMI Rules companion + BreakingChangeDetector.
- Architecture — where CodeGenerationOrchestrator and cascade deployment land.
- Decisions — cross-reference the eight InfiniteCabinet DEC entries in
context/decisions-log.mdfor ADRs we may want to promote into the REV.health DEC-RH series. - v1 Gap Report — the P0 gaps "PMR Deep Exemplar", "Per-module IC-application pages", and "RBAC matrix per module" are partially served by the artifacts adopted on this page.
- Roadmap & Gantt — the ADOPT / ADAPT effort estimates above should feed the platform-level Gantt for Phase 1.