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.
68 lines
2.8 KiB
JavaScript
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);
|
|
}
|