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:
@@ -0,0 +1,69 @@
|
||||
# Nur Falah — Estate & Waqf Suite · Deployment Guide
|
||||
|
||||
**Target:** `moslem04.falahos.my`
|
||||
**Stack:** Svelte 5 + Vite PWA (static SPA), same pattern as `moslem03.falahos.my`
|
||||
**Server:** Docker Swarm (nginx:alpine) on the Contabo VPS, Traefik + Let's Encrypt
|
||||
|
||||
---
|
||||
|
||||
## 1. Build & push image
|
||||
|
||||
```bash
|
||||
docker build -t git.falahos.my/wmj/nur-falah-prevention:latest .
|
||||
docker push git.falahos.my/wmj/nur-falah-prevention:latest
|
||||
```
|
||||
|
||||
## 2. Deploy to the swarm
|
||||
|
||||
```bash
|
||||
docker stack deploy -c deploy/docker-stack.yml nur-falah-prevention
|
||||
```
|
||||
|
||||
Traefik picks up the labels in `deploy/docker-stack.yml` and routes
|
||||
`moslem04.falahos.my` to the service automatically, issuing a Let's Encrypt
|
||||
certificate on first request.
|
||||
|
||||
## 3. DNS
|
||||
|
||||
Point `moslem04.falahos.my` at the same VPS IP already serving `moslem03.falahos.my`
|
||||
(A/AAAA record, or CNAME if using a CDN in front).
|
||||
|
||||
## 4. Verify
|
||||
|
||||
```bash
|
||||
curl -sI https://moslem04.falahos.my/ | grep -i "cache-control"
|
||||
# index.html: cache-control: no-cache, must-revalidate
|
||||
|
||||
curl -sI https://moslem04.falahos.my/sw.js | grep -i "cache-control"
|
||||
# sw.js: cache-control: no-cache, no-store, must-revalidate
|
||||
```
|
||||
|
||||
- [ ] `https://moslem04.falahos.my/` returns 200
|
||||
- [ ] Service worker activates (DevTools → Application → Service Workers)
|
||||
- [ ] App installs as PWA
|
||||
- [ ] All 6 modules load without console errors: Faraid, Assets, Wassiyah, Hibah, Family Waqf, Claims (H2)
|
||||
|
||||
## 5. Rollback
|
||||
|
||||
```bash
|
||||
docker service update --rollback nur-falah-prevention_web
|
||||
```
|
||||
|
||||
## Known gaps before this is production-grade (not blocking this deploy, tracked for follow-up)
|
||||
|
||||
- **Encryption at rest**: storage.js currently uses plain `localStorage`. Horizon 1
|
||||
PRD §10 requires encrypted-at-rest for Asset Registry / wassiyah / hibah / waqf
|
||||
drafts. WebCrypto AES-GCM wrapping is the next hardening step.
|
||||
- **PDF export**: current export is plain-text download + browser print dialog, not
|
||||
a dedicated PDF pipeline. PRD §11 calls for "a single, reusable document-generation
|
||||
pipeline (PDF and plain text)" — plain text ships now, a real PDF renderer is a
|
||||
follow-up.
|
||||
- **Horizon 2 claims module is a local, non-custodial demo only** — see the in-app
|
||||
banner and `src/lib/horizon2/claims.js`. It has no legal wrapper, no institutional
|
||||
partner, and issues no real claim. Built ahead of the Horizon 2 PRD's stated Phase 0
|
||||
gate per explicit product direction — do not represent this screen to any real user
|
||||
as a live programme.
|
||||
- **Family Waqf Designator ships ahead of scholarly sign-off** — `scholarly-review-log.md`
|
||||
OPEN-01 (the waqf one-third cap conflict) is still unresolved. Built per explicit
|
||||
product direction; the in-app copy states this openly rather than presenting
|
||||
invented certainty.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Docker Swarm stack for moslem04.falahos.my
|
||||
# Matches the deploy pattern used for moslem03 (Docker Swarm, nginx:alpine,
|
||||
# Traefik + Let's Encrypt on the Contabo VPS) per UAT-REPORT-moslem03.md in
|
||||
# the hermes-macbookair/nur-falah repo.
|
||||
#
|
||||
# Deploy: docker stack deploy -c deploy/docker-stack.yml nur-falah-prevention
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
web:
|
||||
image: git.falahos.my/wmj/nur-falah-prevention:latest
|
||||
networks:
|
||||
- traefik-public
|
||||
deploy:
|
||||
replicas: 1
|
||||
update_config:
|
||||
order: start-first
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.moslem04.rule=Host(`moslem04.falahos.my`)
|
||||
- traefik.http.routers.moslem04.entrypoints=websecure
|
||||
- traefik.http.routers.moslem04.tls.certresolver=letsencrypt
|
||||
- traefik.http.services.moslem04.loadbalancer.server.port=80
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
@@ -0,0 +1,80 @@
|
||||
# ──────────────────────────────────────────────
|
||||
# Nur Falah — Estate & Waqf Suite · Nginx SPA Config
|
||||
# Target: moslem04.falahos.my
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name moslem04.falahos.my;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
error_page 404 =200 /index.html;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 5;
|
||||
gzip_min_length 512;
|
||||
gzip_types
|
||||
text/html
|
||||
text/plain
|
||||
text/css
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
application/manifest+json
|
||||
image/svg+xml
|
||||
image/x-icon
|
||||
font/woff2;
|
||||
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "0" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "no-cache, must-revalidate" always;
|
||||
}
|
||||
|
||||
location /assets/ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable, max-age=31536000" always;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /favicon.svg {
|
||||
expires 7d;
|
||||
add_header Cache-Control "public, max-age=604800" always;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /manifest.webmanifest {
|
||||
expires 1d;
|
||||
add_header Cache-Control "public, max-age=86400" always;
|
||||
add_header Content-Type "application/manifest+json";
|
||||
}
|
||||
|
||||
location /sw.js {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
add_header Service-Worker-Allowed "/";
|
||||
expires off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|woff2)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable, max-age=31536000" always;
|
||||
}
|
||||
|
||||
location ~* \.(png|ico)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable, max-age=31536000" always;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ~ /\. { deny all; access_log off; log_not_found off; }
|
||||
location ~ ^/(node_modules|src)/ { deny all; access_log off; }
|
||||
}
|
||||
Reference in New Issue
Block a user