@ppankov/pgp-core-domain
v0.1.0-alpha.1
Published
Provider-independent PGP Core domain rules. Pure, side-effect-free. No Base44 or Supabase dependency.
Readme
pgp-core-domain
Provider-independent PGP Core domain rules. Pure, side-effect-free.
Purpose
This package is the first provider-independent domain layer of PGP Core,
extracted as a standalone source workspace. It contains the pure decision,
validation, calculation, and sanitization rules that currently live inline
inside deployed Base44 backend functions. The package has no Base44
dependency and no Supabase dependency — it is plain standard ESM JavaScript
that can be consumed by any runtime that supports ES modules (Base44 Deno
functions via npm:, Supabase Edge Functions, Node, etc.).
Status
- Version:
0.1.0-alpha.1(provisional — see Version pinning below). - Publication status: NOT PUBLISHED. This is a local source workspace only. No npm release has been made. Publication is controlled manually by the repository owner at a later wave. No npm credentials belong in Base44 — the package is authored and published from the repository, not from the Base44 app environment.
- Integration status: NOT INTEGRATED. No deployed Base44 function imports this package yet. The deployed functions still carry their inline copies of the same logic. This temporary duplication is intentional and is resolved only in a later wave (Wave 10.3B) after successful package publication and import verification.
Purity contract
Every file in src/ is provider-independent. Forbidden inside the package:
@base44/sdkor any Base44 API- Deno APIs (
Deno.serve,Deno.env, …) - Supabase or any database client
- React or any browser API
- Node-specific APIs (fs, net, crypto.randomUUID, …)
fetch/ network- filesystem access
- environment variables
- authentication / authorization
- audit writes / event publication
- random UUID generation
- implicit current time (
Date.now(),new Date()with no arg)
Time-dependent functions accept an explicit nowIso (ISO 8601 UTC string) or
nowMs (epoch millis) input. Deterministic Date conversions are allowed
only over explicit input timestamps.
All exported functions:
- do not mutate their inputs;
- have no side effects;
- return plain serializable data;
- preserve the current deployed behavior (no latent-bug fixes in this wave).
Modules
| Module | Exports |
| --- | --- |
| workflowGraph.js | validateWorkflowGraph(graph) |
| jobScheduling.js | buildOccurrenceKey(scheduleId, scheduledForUtcIso), evaluateScheduleOccurrence(input) |
| backgroundJob.js | calculateRetryDelay(retryPolicy, attemptNumber), decideFailedJobTransition(input) |
| safeData.js | containsSecretKey(value), redactSecretKeys(value), sanitizeErrorText(message) |
Public exports (subpath imports)
| Import path | Resolves to |
| --- | --- |
| pgp-core-domain | src/index.js (re-exports all) |
| pgp-core-domain/workflow | src/workflowGraph.js |
| pgp-core-domain/scheduling | src/jobScheduling.js |
| pgp-core-domain/background-job | src/backgroundJob.js |
| pgp-core-domain/safe-data | src/safeData.js |
Version pinning
When integrated, consumers must pin an exact version, e.g.
import { validateWorkflowGraph } from "npm:[email protected]/workflow";
import { evaluateScheduleOccurrence } from "npm:[email protected]/scheduling";
import { decideFailedJobTransition } from "npm:[email protected]/background-job";
import { containsSecretKey, redactSecretKeys, sanitizeErrorText } from "npm:[email protected]/safe-data";The package name (pgp-core-domain) and version are provisional until
verified at the publication gate (registry availability, scope, ownership).
Floating ranges (^, ~) are discouraged for the domain package.
Behavioral parity
The package is a behavioral mirror of the current deployed functions:
validateWorkflowGraph←registerWorkflowVersion/entry.tsandreleaseWorkflowVersion/entry.ts(identical inlinevalidateGraph).evaluateScheduleOccurrence/buildOccurrenceKey←runSchedulerTick/entry.ts(occurrence key + once/interval decision).calculateRetryDelay/decideFailedJobTransition←processBackgroundJobs/entry.ts(retry delay + retry/dead-letter decision).containsSecretKey/redactSecretKeys/sanitizeErrorText←processBackgroundJobs/entry.ts(secret detection / redaction / error text sanitization).
Contract discrepancy findings (Open reconciliation items — NO behavior
change in Wave 10.3A)
Duplicate edge identity (workflow graph)
- Deployed code identity:
from + "|" + to + "|" + label— the edgelabelparticipates in duplicate detection. Two edges with the same(from, to)but different labels are accepted as distinct edges. - Frozen Phase 7 spec identity: repeated
(from, to)pair — the label does not participate; any repeated(from, to)pair is a duplicate.
The package follows deployed behavior to guarantee no runtime semantic change when the package is integrated. The frozen-spec discrepancy is recorded as an open reconciliation item and must be resolved by an explicit decision in a future wave (not by a silent behavior change here).
Verification
cd packages/pgp-core-domain
npm testThe test (test/verify.mjs) is fully self-contained: it uses only
node:assert/strict, no network, no database, no environment variables, no
Base44, no Supabase, no filesystem, no external packages. It prints a single
deterministic summary line on success:
PGP Core domain verification passed: <N> assertions.and exits non-zero on any failure.
Future reuse
- Supabase Edge Functions may import this package directly (it is plain ESM with no Base44 or Deno coupling). Supabase implementation is not started — there is no Supabase client, no migration, no dual-runtime behavior in this package or in the app.
- Base44 Deno functions may import it via the
npm:specifier once published. This is the integration target for Wave 10.3B.
Rollback
To undo Wave 10.3A: delete the packages/pgp-core-domain/ directory and the
corresponding "Wave 10.3A" section in
src/docs/PHASE_10_PORTABILITY_SPEC.md. There are zero runtime behavior
changes and zero deployed-file changes in this wave, so rollback
touches no code outside the package workspace and the spec document.
License
UNLICENSED — internal PGP Core package, not for distribution until a publication decision is made.
