@primocaredentgroup/transcodifica
v0.3.5
Published
Convex component for managing external catalogs, service transcoding and simplified laboratory orders.
Downloads
687
Readme
@primocaredentgroup/transcodifica
Componente Convex per configurazioni di integrazione cliente, cataloghi esterni, mappature verso i servizi di laboratorio e ordini semplificati.
La 0.3.0 espone TranscodificaClient, exposeApi, validator condivisi e il
component source richiesto da Convex. Autenticazione e autorizzazione restano
nel Core host; il browser non passa identità fidate.
Le API list* legacy sono limitate e generano un errore esplicito oltre 200
record. Per dataset completi usare le corrispondenti API paginate*.
Verifica release
npm run codegen
npm run verify
npm pack --dry-runIl modulo migration-kit non è incluso in questa release per decisione esplicita del rollout host.
Prescription catalog and exact mappings
prescriptionCatalog stores each source identity as (clientId, kind, sourceId).
Names and codes can change without recreating catalog items or mappings. Its
sync mutation validates the entire snapshot before writing, preserves existing
IDs and returns { created, updated, unchanged, deactivated }. Only
completeSnapshot: true deactivates previously imported items missing from the
snapshot; partial syncs never disable unrelated entries. Fetch and validate the
entire source response before calling a complete sync.
Atomic sync limits are 2,000 input items and 1 MiB of normalized JSON. Each client
can retain at most 4,000 catalog identities and 4 MiB of normalized catalog JSON,
including inactive history. Names accept 500 characters, descriptions 5,000 and
source IDs/codes 250. Exceeding any limit throws before any write. The host should
report the error and keep the previous catalog available; it must never silently
truncate an import. UI queries use bounded lists (default 100, maximum 200) or
paginateByClient with optional kind and activeOnly filters.
prescriptionMappings maps the exact tuple
(clientId, sourceServiceId, sourceMaterialId, sourceWorkTypeId?) to
labServiceId, labMaterialId and optional labListRowId. An absent work type is
an exact value, never a wildcard. Sources must exist and be active in that
client's imported catalog. A duplicate tuple is rejected even when its mapping
is disabled; use update({ isActive: true }) to reactivate it. Tuple identity is
immutable, while target IDs and notes can be updated. remove disables the
mapping and keeps its audit/history. Every lookup or change by mapping ID also
requires its client ID.
resolve returns { status: "matched", mapping }, or
{ status: "missing" | "inactive" | "stale" | "client_inactive", mapping: null }.
It rechecks the client and each source catalog entry; stale or inactive sources
never resolve. mapping.updatedAt can be recorded by the host alongside the
resolved target as audit evidence. The component treats laboratory target IDs
as opaque: the host must verify them against its laboratory services, material
catalog, list ownership and applicable prices before saving or consuming them.
Legacy serviceMappings and external catalogs are unchanged.
These methods are available on TranscodificaClient with prefixes
prescriptionCatalog* and prescriptionMappings*, and through exposeApi groups
of the same names. All new validators/types are exported from the package root
and /validators. Mapping audit identity is injected by the trusted client
callerTokenIdentifier or withActor(...); exposed functions derive it from the
host authorization hook, never from browser arguments.
Historical migration
/migration exports TranscodingClient.Identity, dependent on Company.Identity.
/migration/validators exports the strict schema and batch/result validators.
Use TranscodificaClient.migration.loadTranscodingClientIdentity through a guarded
internal host mutation. The host must validate the resolved Company really exists.
Input requires original externalId, companyExternalId, clientName,
integrationType, isActive, createdAt and updatedAt; optional deletedAt,
notes, externalCreationTime preserve absence and zero. The physical config ID,
source identity and actual Core Company ID are distinct: only the resolved Company
ID is stored in clientId. No implicit restore, activation, timestamp generation
or business-key upsert occurs. Preview does not write. A replay requires an approved
existingConvexId, matching provenance and identical original fields. Discordant
source/company duplicate groups all fail before writes. Write failures abort the
transaction so host/provider/identity changes can roll back together.
A supplied defaultLabListExternalId is rejected with DEFERRED_LISTINI_REFERENCE.
Raw defaultLabListId is outside the input contract. Historical services, materials,
mappings, orders/items and prescription catalog/mapping tables are not included:
they need their own source key, owner, numbering and Listini contracts. Existing
operational APIs and order-number uniqueness are unchanged. migration.getIdentity
can inspect inactive/deleted imported configs for explicit historical connections.
Historical catalog identities
The migration module adds TranscodingExternalService.Identity,
TranscodingExternalMaterial.Identity and TranscodingPrescriptionCatalog.Identity.
Schemas derive from the provider tables with the official migration-kit helper.
Each requires a qualified original externalId and an explicitly resolved
clientExternalId produced by TranscodingClient.Identity. The consumer must
verify the kit mapping, the provider configuration provenance and its actual
Core Company in the same transaction; each typed catalog loader requires this
host guard. catalogHistory.getIdentity is the minimal historical parent query.
Original code/sourceId/kind, names, prices, flags, dates, absence and deletion
are preserved. migrationOriginal stores the exact source payload separately
from resolved clientId; externalCreationTime is optional. Preview writes nothing;
replay requires an approved physical mapping and identical originals. Collisions
with a source ID or business key stop; there is no CRUD upsert or restoration.
No source key or namespace is inferred from a mutable name/code.
Historical records have migrationPendingActivation: true; operational listing,
lookup, editing, service/order association and prescription resolution cannot use
them. Native imports/sync stop if they would overwrite retained originals.
There is no activation capability. Required inactive/deleted parents are accepted
for historical preservation, and wrong-client/provenance mappings are rejected.
Coverage is 4/8 current provider tables including the existing client config row. The earlier inventory had six tables: prescription_catalog_items and prescription_mappings were added by the prescription feature and are separate new scope. Orders/order_items, service_mappings and prescription_mappings remain without historical loaders. Order-number scope and existing Listini links await owner decisions; no constraint is relaxed implicitly. MySQL mapping and real imports remain separate from provider coverage. The migration-kit repository is unchanged; tests use its official 2.3.10 package. convex-helpers stays pinned to the existing lock version 0.1.123, compatible with Convex 1.44.
Historical rule imports and approved list scope
TranscodingImportScope.Identity binds one existing historical client configuration
and one explicitly approved, existing host Listini list. The provider stores the
binding as immutable historyScope* metadata on client_configs. It does not set
defaultLabListId, change original client flags, or activate an integration. The
host must re-read the Company/client and Listini identity mappings in the same
transaction; source selection must identify the intended company and list explicitly.
Scope replay requires the same source references and physical list. The original
TranscodingClient.Identity replay remains valid after attaching this metadata.
TranscodingServiceMapping.Identity and TranscodingPrescriptionMapping.Identity
import the two rule tables. Validators derive originals from the provider schema.
Original rule PKs identify rows; business combinations never claim existing records.
Service rules resolve original external service/material identities, retaining array
order, an empty array, or absence. Prescription rules resolve catalog identities by
client and exact kind, retaining each catalog's original sourceId. Optional work type
and original list-row absence are preserved. Actors, flags, timestamps, snapshots,
zero values and empty notes are never regenerated.
The host must supply verified existing TranscodingListiniService.Identity,
TranscodingListiniRow.Identity (when present), and TranscodingLabMaterial.Identity
bindings. It must verify that targets belong to the approved list, and a selected row
contains the selected service. Provider catalog parents must have matching original
provenance and client; inactive/deleted originals are allowed for preservation.
Typed client.ruleHistory writes require a host guard callback. Never expose a raw
provider capability as an unguarded host import endpoint.
Preview does not write. Exact replay checks approved mappings and original values;
conflicting duplicate groups and native business-key collisions stop before writes.
Unexpected write failures propagate for transactional rollback. Rule records retain
original active flags behind migrationPendingActivation: native lists/pagination,
lookup/resolution, updates, deletes and bulk operations cannot consume or overwrite
them. Activation and operational client-domain alignment are separate tasks.
The module now includes seven rows covering six provider tables. orders and
order_items have no historical loader. In PrimoLabCore the owner confirmed that old
orders are Core prescriptions with unique original IDs and numberText; do not create
a second archive in Transcodifica. This source-scope decision belongs to that consumer.
