Files
nur-falah-prevention/src/lib/horizon2/claims.js
T
wmj e87e329731 docs: resolve both governance gates (OPEN-01, Horizon 2 Phase 0)
OPEN-01 (scholarly-review-log.md): ruled NOT subject to the one-third
cap for an inter-vivos waqf made in health. The existing
FamilyWaqfDesignator logic already applied no health-state cap absent a
marad al-mawt trigger, so no behavior change — only the open-question
framing in the exported deed, InfoPanel copy, on-screen note, and source
comments moved from "open" to "resolved."

Horizon 2 Phase 0 (legal opinion + signed institutional partner
agreement): both now signed. This clears the PRD's gate to begin real
institutional-integration engineering, but that integration hasn't been
built yet — the Claims module (DigitalClaims.svelte, claims.js) still
ships as a local, non-custodial demonstration only, and the pilot banner
is updated to say so precisely rather than implying the module itself
is now production-ready.

Updated README.md and deploy/DEPLOY.md to match.
2026-10-23 10:40:26 +08:00

68 lines
2.8 KiB
JavaScript

// Digital Beneficial Claims data model.
// Originally built ahead of Horizon 2 PRD's stated gate: "No engineering work begins
// until Phase 0 (legal opinion + signed institutional partner agreement) is
// complete." Phase 0 is now RESOLVED — both are signed, clearing the way to build
// the real legal wrapper (SPV/trust, Horizon 2 PRD §5.1) and institutional
// integration. Neither has been built yet, so this module still ships as a local,
// non-custodial demonstration only, structurally enforcing the PRD §5.2 transfer
// restriction (no open market). Nothing here moves real assets or represents a real
// legal claim until that integration work lands.
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);
}