Skip to content

Commit b00cbaa

Browse files
Miz Causevicclaude
andcommitted
feat(v0.1-shipped): initial operator surface
Single-page static HTML operator dashboard with: - 4-tab pattern (overview · anomalies · external sync · audit chain) - ~30 entities of synthetic data baked in (no backend, no telemetry) - Anomaly-detection cards with specific regulatory anchors - External system sync state matrix - ed25519-signed hash-chained audit-stream events - Apex-aligned visual language (onyx + cream + emerald, mono nav, rounded-pill CTA, KG SVG mark) - Security headers via .htaccess (CSP / HSTS / XFO / XCTO / Referrer-Policy / COEP / CORP / Permissions-Policy) - FTP-Deploy-Action workflow for Hostinger native git pull Status: v0.1-shipped (MVP). Hardening to v1.0-prod is a separate squad- discipline pass (CI green, vitest test suite, screenshot fixtures, scripts/ helpers, .release-notes.md). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 parents  commit b00cbaa

9 files changed

Lines changed: 1040 additions & 0 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Deploy to Hostinger
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
concurrency:
12+
group: deploy-${{ github.ref }}
13+
cancel-in-progress: false
14+
15+
jobs:
16+
deploy:
17+
name: FTP-sync static surface to pv.kineticgain.com
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 10
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Verify build
25+
run: |
26+
test -f index.html || (echo "FAIL: index.html missing" && exit 1)
27+
test -f .htaccess || (echo "FAIL: .htaccess missing" && exit 1)
28+
grep -q "Pharmacovigilance Review and Reporting Hub" index.html || (echo "FAIL: index.html missing title" && exit 1)
29+
echo "OK: verified"
30+
ls -lah
31+
32+
- name: FTP Deploy
33+
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
34+
with:
35+
server: ${{ secrets.FTP_SERVER }}
36+
username: ${{ secrets.FTP_USERNAME }}
37+
password: ${{ secrets.FTP_PASSWORD }}
38+
local-dir: ./
39+
server-dir: /pv/
40+
exclude: |
41+
**/.git*
42+
**/.git*/**
43+
**/.github/**
44+
**/node_modules/**
45+
README.md
46+
CHANGELOG.md
47+
LICENSE
48+
49+
- name: Verify live
50+
run: |
51+
sleep 30
52+
curl -fsSL --max-time 15 "https://pv.kineticgain.com/" > /tmp/live.html || exit 1
53+
grep -q "Pharmacovigilance Review and Reporting Hub" /tmp/live.html || (echo "FAIL: live render missing title" && exit 1)
54+
echo "OK: live at https://pv.kineticgain.com/"

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules/
2+
dist/
3+
.DS_Store
4+
*.log
5+
.vite/
6+
*.tsbuildinfo
7+
.env
8+
.env.local

.htaccess

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Security headers — buyer-facing operator surface
2+
# Set as response headers (NOT meta tags — frame-ancestors, HSTS, X-Frame-Options
3+
# CANNOT be set via <meta>).
4+
5+
<IfModule mod_headers.c>
6+
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
7+
Header always set X-Frame-Options "DENY"
8+
Header always set X-Content-Type-Options "nosniff"
9+
Header always set Referrer-Policy "strict-origin-when-cross-origin"
10+
Header always set Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"
11+
Header always set Cross-Origin-Opener-Policy "same-origin"
12+
Header always set Cross-Origin-Resource-Policy "same-origin"
13+
Header always set Cross-Origin-Embedder-Policy "require-corp"
14+
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; font-src 'self' data:; img-src 'self' data: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests"
15+
Header unset Server
16+
Header unset X-Powered-By
17+
</IfModule>
18+
19+
# Force HTTPS
20+
<IfModule mod_rewrite.c>
21+
RewriteEngine On
22+
RewriteCond %{HTTPS} off
23+
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
24+
</IfModule>
25+
26+
# MIME types
27+
AddType image/svg+xml .svg
28+
AddType application/json .json
29+
30+
# Cache-Control
31+
<FilesMatch "\.(html)$">
32+
Header set Cache-Control "no-cache, must-revalidate"
33+
</FilesMatch>
34+
<FilesMatch "\.(css|js|svg|png|jpg|woff2)$">
35+
Header set Cache-Control "public, max-age=604800"
36+
</FilesMatch>

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Changelog
2+
3+
## v0.1-shipped — 2026-06-02
4+
5+
Initial MVP scaffold:
6+
7+
- Single-page static HTML operator surface
8+
- Synthetic data baked in (no backend, no login, no telemetry)
9+
- 4-tab dashboard pattern (overview · anomalies · sync state · audit chain)
10+
- Audit-stream binding (decision events as a verifiable chain)
11+
- AGPL-3.0 license
12+
- Hostinger FTP deploy via GitHub Actions
13+
- Security headers via .htaccess (CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy)
14+
- Apex-aligned visual language (Geist + Geist Mono, onyx + cream + emerald)
15+
16+
Next: `v1.0-prod` hardening — CI green, vitest test suite, screenshot fixtures, scripts/ helpers, .release-notes.md.

CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pv.kineticgain.com

0 commit comments

Comments
 (0)