Initial build: Horizon 1 Prevention Suite + Horizon 2 Unlock demo

Svelte 5 + Vite PWA, styled to match moslem03.falahos.my's design system.

Horizon 1: Faraid Calculator (shared calc core, 14 classical cases passing),
Asset Registry, Wassiyah Generator (1/3 meter + heir-exclusion block),
Hibah Tracker and Family Waqf Designator (shared marad al-mawt guardrail).

Horizon 2: Digital Beneficial Claims — local non-custodial demo of the claim
model and transfer restriction only.

Two governance gates in this project's own PRDs were overridden per explicit
product direction, and are flagged in-app and in README.md / deploy/DEPLOY.md
rather than silently shipped as production-ready:
- Family Waqf Designator ships ahead of scholarly sign-off (OPEN-01 in
  scholarly-review-log.md remains unresolved).
- Horizon 2 ships ahead of the PRD's stated Phase 0 gate (legal opinion +
  signed institutional partner) with no confirmation that gate is cleared.
This commit is contained in:
wmj
2026-08-13 16:55:58 +08:00
commit 6690696f7f
28 changed files with 7586 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
// Digital Beneficial Claims data model.
// Built per explicit user instruction overriding Horizon 2 PRD's stated gate:
// "No engineering work begins until Phase 0 (legal opinion + signed institutional
// partner agreement) is complete." No evidence Phase 0 is complete — this ships as
// a local, non-custodial demonstration model only, structurally enforcing the
// PRD §5.2 transfer restriction (no open market) even though the real legal
// wrapper (SPV/trust, Horizon 2 PRD §5.1) and institutional integration do not exist
// yet. Nothing here moves real assets or represents a real legal claim.
import { load, save } from '../storage.js';
const KEY = 'h2Claims';
/**
* @param {object} params { assetId, assetLabel, heirPoolId, holderName, heirShareFraction, faraidRulingRef }
*/
export function issueClaim(params) {
const claims = load(KEY, []);
const claim = {
id: crypto.randomUUID(),
status: 'issued', // issued | transferred | bought-back
issuedAt: new Date().toISOString(),
history: [{ event: 'issued', at: new Date().toISOString(), to: params.holderName }],
...params
};
claims.push(claim);
save(KEY, claims);
return claim;
}
export function listClaims() {
return load(KEY, []);
}
/**
* Transfer restriction per Horizon 2 PRD §5.2: a claim may only transfer to
* (a) another verified heir within the same heir pool for that asset, or
* (b) the legal wrapper entity itself (buy-back). No default path to an open market —
* structurally enforced here, not left to UI copy alone.
*/
export function transferClaim(claimId, { toHolderName, toHeirPoolId, mode }) {
const claims = load(KEY, []);
const claim = claims.find(c => c.id === claimId);
if (!claim) throw new Error('Claim not found');
if (mode === 'buy-back') {
claim.status = 'bought-back';
claim.history.push({ event: 'buy-back', at: new Date().toISOString(), note: 'valuation set by independent valuation, not a market bid (demo: no real valuation engine wired)' });
} else if (mode === 'heir-pool-transfer') {
if (toHeirPoolId !== claim.heirPoolId) {
throw new Error('BLOCKED: recipient is not in the same faraid-determined heir pool for this asset. Per PRD §5.2 there is no default path to an open market.');
}
claim.holderName = toHolderName;
claim.status = 'transferred';
claim.history.push({ event: 'transfer', at: new Date().toISOString(), to: toHolderName });
} else {
throw new Error('Unsupported transfer mode — pre-approved licensed institutional buyer flow requires a separately reviewed compliance process not modelled here.');
}
save(KEY, claims);
return claim;
}
export function removeClaim(claimId) {
const claims = load(KEY, []).filter(c => c.id !== claimId);
save(KEY, claims);
}