{"id":51025387,"url":"https://github.com/edycutjong/epoch","last_synced_at":"2026-06-21T19:01:53.991Z","repository":{"id":366066845,"uuid":"1274944252","full_name":"edycutjong/epoch","owner":"edycutjong","description":"⏳ Verifiable, privacy-blind inheritance and continuity orchestration inside hardware-isolated enclaves.","archived":false,"fork":false,"pushed_at":"2026-06-20T04:59:45.000Z","size":2861,"stargazers_count":0,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-20T06:20:28.235Z","etag":null,"topics":["cryptography","dead-mans-switch","intel-tdx","nextjs","rust","tee","webassembly"],"latest_commit_sha":null,"homepage":"https://epoch.edycu.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edycutjong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-20T04:14:16.000Z","updated_at":"2026-06-20T05:05:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/edycutjong/epoch","commit_stats":null,"previous_names":["edycutjong/epoch"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/edycutjong/epoch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fepoch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fepoch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fepoch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fepoch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edycutjong","download_url":"https://codeload.github.com/edycutjong/epoch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fepoch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34622271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","dead-mans-switch","intel-tdx","nextjs","rust","tee","webassembly"],"created_at":"2026-06-21T19:01:52.715Z","updated_at":"2026-06-21T19:01:53.983Z","avatar_url":"https://github.com/edycutjong.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n  \u003cimg src=\"docs/icon-animated.svg\" alt=\"Epoch Icon\" width=\"120\"\u003e\n  \u003ch1\u003eEpoch ⏳\u003c/h1\u003e\n  \u003cp\u003e\u003cem\u003eVerifiable, privacy-blind inheritance and continuity orchestration inside hardware-isolated enclaves.\u003c/em\u003e\u003c/p\u003e\n  \u003cimg src=\"docs/readme-hero.svg\" alt=\"Epoch — TEE Dead-Man's Switch\" width=\"100%\"\u003e\n\n  \u003cbr/\u003e\n\n  [![Live Demo](https://img.shields.io/badge/🚀_Live-Demo-06b6d4?style=for-the-badge)](https://epoch.edycu.dev)\n  [![Pitch Video](https://img.shields.io/badge/🎬_Pitch-Video-ef4444?style=for-the-badge)](https://youtu.be/your-video)\n  [![Pitch Deck](https://img.shields.io/badge/📊_Pitch-Deck-f59e0b?style=for-the-badge)](https://epoch.edycu.dev/pitch.html)\n  [![Built for T3ADK](https://img.shields.io/badge/DoraHacks-T3ADK_Launch_2026-8b5cf6?style=for-the-badge)](https://dorahacks.io/hackathon/t3adkdevchallenge)\n\n  \u003cbr/\u003e\n\n  ![Next.js](https://img.shields.io/badge/Next.js_16-black?style=flat\u0026logo=next.js)\n  ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat\u0026logo=typescript\u0026logoColor=white)\n  ![Rust WASM](https://img.shields.io/badge/Rust_WASM-de782f?style=flat\u0026logo=rust\u0026logoColor=white)\n  ![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=flat\u0026logo=tailwindcss\u0026logoColor=white)\n  ![Intel TDX](https://img.shields.io/badge/Intel_TDX-0071c5?style=flat\u0026logo=intel\u0026logoColor=white)\n  ![T3 ADK](https://img.shields.io/badge/T3_ADK-8b5cf6?style=flat)\n  [![CI](https://github.com/edycutjong/epoch/actions/workflows/ci.yml/badge.svg)](https://github.com/edycutjong/epoch/actions/workflows/ci.yml)\n\n\u003c/div\u003e\n\n---\n\n\u003e ⚡ **Reviewers / judges:** fastest path is **[GOLDEN_PATH.md](GOLDEN_PATH.md)** — the entire flow in ~2 minutes, **no credentials**. Bug-bounty track: **[SDK_AUDIT.md](docs/SDK_AUDIT.md)** (confirmed, code-cited findings from the real `@terminal3` SDK). API reference: **[API.md](API.md)**.\n\n## 📸 See it in Action\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"public/og-image.png\" alt=\"Epoch Dashboard Mockup\" width=\"100%\"\u003e\n\u003c/div\u003e\n\n\u003e **Arm switch** → **Pulse heartbeats inside TDX Enclave** → **Countdown triggers blind legacy cascade** if check-in goes silent.\n\n---\n\n## 💡 The Problem \u0026 Solution\n\nAfter a serious medical diagnosis or for secure institutional continuity, users need a way to pass on secrets (credentials, private keys, final instructions) to heirs if they become unresponsive. However, handing over a complete digital life to a centralized custodian or tech startup today is a privacy nightmare.\n\n**Epoch** solves this by leveraging a TEE-secured dead-man's switch running inside **Intel TDX enclaves**. Secrets remain fully sealed and encrypted until the countdown condition expires. Heartbeats are verified with TOTP OTP codes inside the enclave, and beneficiaries are reached at the edge using privacy-blind egress channels.\n\n### Key Features:\n- 🛡️ **Intel TDX Hardware Enclaves**: Host-isolated boundary ensures that no host admin or cloud provider can access the sealed vault files or decryption keys before expiry.\n- ⚡ **Atomic Cascade Rollbacks**: Downstream legacy release executes as a single transactional unit; reverts and rolls back fully if any downstream target fails.\n- 🔒 **Privacy-Blind Egress**: Substitutes PII markers (e.g. `{{profile.email}}`) at the egress boundary using `http-with-placeholders`, so the enclave never leaks contact details.\n- 🕰️ **Monotonic Clock Guard**: Hardened liveness checks rely on the enclave's secure monotonic clock, making countdowns immune to host clock tampering.\n\n---\n\n## 🏗️ Architecture \u0026 Tech Stack\n\n| Layer | Technology |\n|---|---|\n| **Frontend UI** | Next.js 16 (App Router), React 19, Tailwind CSS |\n| **Secure Enclave** | Intel TDX TEE |\n| **Contract / Core Logic** | **Two** Rust→WASM enclave contracts (`wasm32-unknown-unknown`): the **Switch Coordinator** (`contract/`) and the **Egress Dispatcher** (`contract-executor/`) |\n| **Integrations** | 8 Terminal 3 ADK Host APIs — `kv-store`, `clock`, `signing`, `stash`, `logging`, `contracts-call`, `outbox`, `http-with-placeholders` |\n| **E2E Testing** | Playwright |\n| **Performance Audit** | Lighthouse CI + `scripts/bench.py` |\n\n### Two-Contract Atomic Cascade:\nThe **Switch Coordinator** never performs egress itself. When a switch expires it invokes the **Egress Dispatcher** (\"Blind Courier\") synchronously via `contracts-call`. The whole release is one atomic transaction: if the Dispatcher reports any failed delivery, the Coordinator aborts — the switch is **not** marked fired, **no** VC is issued, and **nothing** is enqueued to the durable outbox, so the vault keys stay sealed.\n\n```mermaid\ngraph TD\n    A[User Heartbeat] --\u003e|Valid OTP Check-in| B(Switch Coordinator · WASM #1)\n    B --\u003e|Silent Timeout · monotonic clock| C[Expired Status]\n    C --\u003e|fire_epoch| B\n    B --\u003e|host_contracts_call| D(Egress Dispatcher · WASM #2)\n    D --\u003e|http-with-placeholders| F[Beneficiaries · PII-blind]\n    D --\u003e|success/failure| B\n    B --\u003e|on success: signing VC + stash audit + outbox| G[(Durable Outbox)]\n    B --\u003e|on failure: ROLLBACK| H[Keys stay sealed]\n    style B fill:#ffaa00,stroke:#333,stroke-width:2px,color:#000\n    style D fill:#00f0ff,stroke:#333,stroke-width:2px,color:#000\n    style G fill:#22c55e,stroke:#333,stroke-width:2px,color:#fff\n    style H fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff\n```\n\n---\n\n## 🏆 Sponsor Tracks Targeted\n\n### T3 ADK Developer Track — 8 Host APIs across 2 enclave contracts\n\n**Switch Coordinator** ([`contract/src/lib.rs`](contract/src/lib.rs)):\n- **`kv-store`**: Sealed storage of switch config and encrypted vault keys (`host_kv_store_get` / `host_kv_store_set`).\n- **`clock`**: Monotonic countdown evaluation + TOTP time-window, immune to NTP tampering (`host_clock_now`).\n- **`signing`**: Issues a W3C `LegacyReleaseCredential` VC receipt for the cascade. The host signing service uses the **real published Terminal 3 SDK** — [`@terminal3/ecdsa_vc`](https://www.npmjs.com/package/@terminal3/ecdsa_vc) to issue a genuine `EcdsaSecp256k1Signature2019` credential and [`@terminal3/verify_vc`](https://www.npmjs.com/package/@terminal3/verify_vc) to verify it (offline, no credentials — see [`src/lib/realVc.ts`](src/lib/realVc.ts), [`/api/verify-vc`](src/app/api/verify-vc/route.ts), and `test/realVc.test.ts`). A tampered VC fails verification.\n- **`stash`**: Retrieves sealed vault files and uploads the release audit manifest (`host_stash_get` / `host_stash_put`).\n- **`logging`**: In-enclave audit trace (`host_logging_log`).\n- **`contracts-call`** ⭐: Synchronously invokes the Egress Dispatcher contract as an atomic sub-transaction (`host_contracts_call`).\n- **`outbox`**: Durable, idempotent (`idk`-keyed) enqueue of the release event on success (`host_outbox_enqueue`).\n\n**Egress Dispatcher** ([`contract-executor/src/lib.rs`](contract-executor/src/lib.rs)):\n- **`http-with-placeholders`** ⭐: PII-blind beneficiary egress — substitutes `{{profile.*}}` markers at the host boundary so neither contract sees plaintext contacts (`host_http_with_placeholders_post`).\n- **`logging`**: Courier-side delivery trace (`host_logging_log`).\n\n\n---\n\n## 🚀 Getting Started\n\n### Prerequisites\n- Node.js ≥ 20\n- Rust Toolchain with `wasm32-unknown-unknown` target:\n  ```bash\n  rustup target add wasm32-unknown-unknown\n  ```\n\n### Installation \u0026 Local Setup\n\n1. **Clone the repository:**\n   ```bash\n   git clone https://github.com/edycutjong/epoch.git\n   cd epoch\n   ```\n\n2. **Install dependencies:**\n   ```bash\n   npm install\n   ```\n\n3. **Compile both WASM enclave contracts:**\n   ```bash\n   # Builds the Switch Coordinator + Egress Dispatcher and copies both into src/lib/\n   make build-contracts\n   ```\n   \u003cdetails\u003e\u003csummary\u003e…or manually\u003c/summary\u003e\n\n   ```bash\n   cargo build --manifest-path contract/Cargo.toml --target wasm32-unknown-unknown --release\n   cargo build --manifest-path contract-executor/Cargo.toml --target wasm32-unknown-unknown --release\n   mkdir -p src/lib\n   cp contract/target/wasm32-unknown-unknown/release/epoch_contract.wasm src/lib/\n   cp contract-executor/target/wasm32-unknown-unknown/release/epoch_executor.wasm src/lib/\n   ```\n   \u003c/details\u003e\n\n4. **Setup Environment:**\n   ```bash\n   cp .env.example .env\n   ```\n\n5. **Run Development Server:**\n   ```bash\n   npm run dev\n   ```\n\n---\n\n## 🧪 Testing \u0026 CI\n\nWe enforce a **6-stage pipeline**: Quality → Security → Build → E2E → Performance → Deploy.\n\n```bash\n# ── Local Automation ────────────────────────\nmake test-contract # Run Rust enclave contract unit tests (both contracts)\nmake e2e           # Run Playwright E2E tests\nmake lighthouse    # Run Lighthouse CI performance audit\nmake security-scan # Run high/critical security scan\n\n# ── Code Quality ────────────────────────────\nnpm run lint       # Lint check\nnpm run typecheck  # TypeScript compiler check\nnpm run test       # Run unit tests (Vitest)\n\n# ── Performance ─────────────────────────────\nnpm run dev \u0026              # start the app\npython3 scripts/bench.py   # measure p50/p95 latency (stdlib only)\n```\n\n| Layer | Tool | Status |\n|---|---|---|\n| Code Quality | ESLint + TypeScript | ✅ Passed |\n| Unit Testing (TS) | Vitest — **193 tests** | ✅ Passed |\n| Contract Testing (Rust) | cargo — **26 tests** (20 Coordinator + 6 Dispatcher) | ✅ Passed |\n| E2E Testing | Playwright (3 suites) | ✅ Passed |\n| Security (SAST) | CodeQL | ✅ Active |\n| Security (SCA) | Dependabot + npm audit | ✅ Clean |\n| Secret Scanning | TruffleHog | ✅ Configured |\n| Performance | Lighthouse CI + `bench.py` | ✅ Configured |\n\n### ⚡ Runtime Latency (local sandbox)\n\nMeasured with `scripts/bench.py` (100 iterations + 10 warmup) against `npm run dev` on Apple Silicon. Representative numbers — re-run to reproduce:\n\n| Path | p50 | p95 | p99 |\n|---|---|---|---|\n| `get_status` (WASM) | 4.1 ms | 10.8 ms | 11.9 ms |\n| `check_trigger` (WASM) | 3.8 ms | 5.9 ms | 13.5 ms |\n| `integrations/verify` (host) | 2.7 ms | 4.9 ms | 5.8 ms |\n| **`arm + expire + fire` cascade** | **15.5 ms** | **22.0 ms** | **26.6 ms** |\n\n\u003e The full-cascade row exercises the real path: a synchronous **`contracts-call`** into the Egress Dispatcher contract, **`http-with-placeholders`** egress, **`signing`** VC issuance, a **`stash`** audit upload, and a durable **`outbox`** enqueue — all as one atomic transaction.\n\n---\n\n## 📁 Project Structure\n\n```\nepoch/\n├── docs/              # Documentation and presentation assets\n│   ├── assets/\n│   │   ├── screenshots/  # Walkthrough screenshots (01 to 08)\n│   │   └── icon-512.png\n│   ├── readme-hero.svg\n│   └── PITCH_DECK.md\n├── src/\n│   ├── app/           # Next.js 16 App Router Pages\n│   ├── components/    # React 19 Components\n│   ├── lib/           # Compiled enclave WASM (x2) \u0026 Client API Wrappers\n│   └── theme/         # Tailwind CSS design system snippet\n├── contract/          # Switch Coordinator — Rust/WASM TEE contract (#1)\n├── contract-executor/ # Egress Dispatcher — Rust/WASM TEE contract (#2)\n├── API.md             # Next.js Enclave API Routes documentation\n├── GOLDEN_PATH.md     # 2-Minute Reviewer Quickstart Guide\n├── e2e/                # Playwright E2E Tests\n├── test/               # Vitest Integration Tests\n├── scripts/            # seed.py, bench.py, submission checks\n├── .github/           # GitHub Actions CI Workflows\n├── BUGS.md            # T3 ADK bug/gap audit (Track 2)\n├── eslint.config.mjs  # ESLint 9 configuration\n├── Makefile           # Local Automation Targets\n├── lighthouserc.json  # Lighthouse CI audit config\n└── README.md          # You are here\n```\n\n---\n\n## 🧠 Terminal 3 ADK Dev Challenge: Audit \u0026 Discovered Bugs\n\nThis project is submitted to the **Terminal 3 ADK Dev Challenge 2026** as part of the **Vouch Suite** (a 5-enclave system including Epoch, Lethe, Silo, Synod, and Visor).\n\nWhile building these enclaves we audited the T3 ADK host APIs and SDK and documented **9 concrete onboarding bugs and documentation gaps** — each with a repro, impact, and the workaround we shipped — for the **Track 2 bug bounty**.\n\n➡️ **See [BUGS.md](BUGS.md)** for the full audit. Highlights:\n\n- **Bug #2 — `kv-store` interface discrepancy:** WIT declares `get(map-name, key)` but the C ABI is flat `(key_ptr, key_len)`.\n- **Bug #3 — `clock` name mismatch:** docs say `host_clock_now() -\u003e u64`; WIT requires `now-ms() -\u003e result\u003cu64, clock-error\u003e`.\n- **Bug #4 — `signing` has no VC helper:** templates call `host_signing_issue_vc`, but WIT only exposes raw `sign`.\n- **Gap #6 — tenant DID hex double-encoding** silently breaks KV routing.\n- **Gap #8 / #9 — rollback boundary \u0026 `outbox` idempotency window** are unspecified — both directly affect Epoch's atomic cascade.\n\n---\n\n## 📄 License\n\n[MIT](LICENSE) © 2026 Edy Cu\n\n---\n\n## 🙏 Acknowledgments\n\nBuilt for the DoraHacks T3ADK Launch Edition 2026. Thank you to the Terminal 3 team for the enclaves environment and development tools.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedycutjong%2Fepoch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedycutjong%2Fepoch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedycutjong%2Fepoch/lists"}