Skip to content

Commit 0c0405a

Browse files
committed
chore: initial public release (v1.0.0)
T3 Programmable Fiat Framework — an EIP-2535 Diamond ERC-20 deposit token with programmable transfer envelopes and per-bank claim attribution, targeting a permissioned Hyperledger Besu consortium. This repository is a published snapshot, not the development repository. Each release is a single commit containing the full tree at that version. See the "Releases and repository model" section of README.md for why. Licensed under Apache-2.0. Not production-audited; see NOTICE, REGULATORY-STATUS.md and KNOWN-ISSUES.md for scope, open legal/compliance questions, and known limitations.
0 parents  commit 0c0405a

405 files changed

Lines changed: 141118 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# =============================================================================
2+
# T3 Programmable Fiat Framework — root environment example
3+
# Copy to `.env` and fill in. For local development you can run entirely against
4+
# a local chain; no real keys or testnet access are required.
5+
# Per-service examples also exist: indexer/.env.example, ui-management/.env.example
6+
# =============================================================================
7+
8+
# =============================================================================
9+
# Core Addresses (populated after you deploy locally)
10+
# =============================================================================
11+
DIAMOND_ADDRESS=0xYOUR_DIAMOND_ADDRESS
12+
FORWARDER_ADDRESS=0xYOUR_FORWARDER_ADDRESS
13+
TARGET_ADDRESS=0xYOUR_DEFAULT_TARGET_ADDRESS
14+
RECIPIENT_ADDRESS=0xYOUR_DEFAULT_RECIPIENT_ADDRESS
15+
16+
# =============================================================================
17+
# Local chain (Hardhat node or local Besu devnet)
18+
# =============================================================================
19+
RPC_URL=http://127.0.0.1:8545
20+
NETWORK_LABEL=localhost
21+
22+
# Local Besu devnet (used by the `besu-local` Hardhat network).
23+
BESU_LOCAL_RPC_URL=http://127.0.0.1:8545
24+
# LOCAL-DEV-ONLY: the well-known public Hardhat account #0 key is used by default
25+
# (prefunded in the local Besu genesis). Only set this when targeting a real node.
26+
# BESU_LOCAL_PRIVATE_KEY=0xYOUR_LOCAL_DEPLOYER_KEY
27+
28+
# Solidity build overrides (optional)
29+
# OPT_RUNS=100
30+
# VIA_IR=true
31+
# EVM_VERSION=paris
32+
33+
# =============================================================================
34+
# Relayer (ERC-2771 meta-transaction forwarder)
35+
# =============================================================================
36+
RELAYER_PRIVATE_KEY=0xYOUR_RELAYER_PRIVATE_KEY
37+
ALLOWED_TO=0xYOUR_DIAMOND_ADDRESS
38+
ALLOWED_SELECTORS=0xa9059cbb
39+
MAX_GAS=1500000
40+
MAX_TTL_SECONDS=1209600
41+
RATE_WINDOW_MS=60000
42+
RATE_LIMIT=1000
43+
OBSERVATION_MODE=false
44+
ENFORCE_WARN_AT=1000
45+
ENFORCE_DENY_AT=1000
46+
PORT=8080
47+
48+
# =============================================================================
49+
# UI (Next.js) — see ui-management/.env.example for the full list
50+
# =============================================================================
51+
NEXT_PUBLIC_LOCAL_DIAMOND_ADDRESS=0xYOUR_DIAMOND_ADDRESS
52+
NEXT_PUBLIC_LOCAL_FORWARDER_ADDRESS=0xYOUR_FORWARDER_ADDRESS
53+
NEXT_PUBLIC_PONDER_URL=http://localhost:42070/
54+
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=YOUR_PROJECT_ID
55+
56+
# =============================================================================
57+
# Indexer (Ponder) — see indexer/.env.example for the full list
58+
# =============================================================================
59+
PONDER_RPC_URL=http://127.0.0.1:8545
60+
PONDER_DIAMOND_ADDRESS=0xYOUR_DIAMOND_ADDRESS

.github/workflows/ci.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
contracts:
11+
name: Contracts (compile, test, gates)
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: "22"
18+
cache: "npm"
19+
- name: Install
20+
run: npm ci
21+
- name: Compile
22+
run: npm run compile
23+
- name: Test
24+
run: npm test
25+
- name: Selector collision check
26+
run: node scripts/selector-collision-check.js
27+
- name: Manifest ↔ ABI parity
28+
run: node scripts/check-manifest-abi-parity.js
29+
- name: Storage layout gate
30+
run: node scripts/check-storage-layout.js
31+
- name: Contract size gate
32+
run: node scripts/check-contract-size.js
33+
- name: Doc-claim gate (references in shipping STATUS docs must resolve)
34+
run: node scripts/check-doc-claims.js
35+
36+
secrets:
37+
name: Secret scan (gitleaks)
38+
runs-on: ubuntu-latest
39+
permissions:
40+
contents: read
41+
pull-requests: read # gitleaks-action lists PR commits via the API to scope the scan
42+
steps:
43+
- uses: actions/checkout@v4
44+
with:
45+
fetch-depth: 0
46+
- name: gitleaks
47+
uses: gitleaks/gitleaks-action@v2
48+
env:
49+
# gitleaks-action v2 requires GITHUB_TOKEN to scan pull_request events.
50+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51+
GITLEAKS_CONFIG: .gitleaks.toml
52+
# No PR comments (avoids needing pull-requests: write); the run status is enough.
53+
GITLEAKS_ENABLE_COMMENTS: "false"

.gitignore

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Environment files — CRITICAL: contains private keys and secrets
2+
.env
3+
.env.*
4+
!.env.example
5+
6+
# Generated local Besu devnet keys/genesis
7+
.besu-local/
8+
9+
# Build artifacts and cache
10+
/node_modules
11+
**/node_modules/
12+
/artifacts/*
13+
artifacts/*
14+
/cache
15+
/dist
16+
17+
# Build output
18+
/ui-management/.next
19+
/ui-management/tsconfig.tsbuildinfo
20+
21+
# Deployment tarballs — regenerable from source
22+
*.tar.gz
23+
24+
# Coverage and test reports — regenerable
25+
coverage/
26+
coverage.json
27+
playwright-report/
28+
test-results/
29+
test/test-results/
30+
**/.last-run.json
31+
32+
# Generated reports
33+
gasReport.md
34+
contract-size-report.txt
35+
reports/
36+
37+
# Temporary files
38+
~$*
39+
*.exp
40+
*.tmp
41+
*.temp
42+
43+
# macOS specific
44+
.DS_Store
45+
**/.DS_Store
46+
*/*.DS_Store
47+
48+
# IDE files
49+
.vscode/settings.json
50+
.gemini/
51+
.auto-claude/
52+
.auto-claude-security.json
53+
.auto-claude-status
54+
.claude/settings.local.json
55+
.claude_settings.json
56+
.worktrees/
57+
.security-key
58+
logs/security/
59+
60+
# Third-party agent/tool config stubs (not project source)
61+
.agent/
62+
.roo/
63+
.continue/
64+
.vivus/
65+
.wake/
66+
67+
# Auth credentials
68+
gha-creds-*.json
69+
70+
# NotebookLM extract (regenerated via scripts/export-notebooklm-docs.js)
71+
T3-NotebookLM-Sources/
72+
73+
# Local deployment artifact (consumed by e2e relayer tests; regenerated on deploy)
74+
.forwarder_address

.gitleaks.toml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Gitleaks configuration — T3 Programmable Fiat Framework
2+
#
3+
# Extends the default ruleset and adds project-specific rules for credential
4+
# shapes the default rules do NOT match.
5+
#
6+
# POLICY: new secrets are remediated, never suppressed. The allowlist below
7+
# covers only values that are public by construction (EVM addresses, the
8+
# well-known Anvil test keys). There are no commit-SHA suppressions: this repo
9+
# publishes as a files-only snapshot with no git history, so there is no history
10+
# for a scanner to trip over.
11+
#
12+
# ⚠️ A CLEAN SCAN IS NECESSARY, NOT SUFFICIENT.
13+
# Gitleaks matches known secret SHAPES. On 2026-08-25 it reported "no leaks
14+
# found" against a tree that contained a live root SSH password twelve times —
15+
# once in a JSON-escaped tool-permission string, and eleven times inside expect
16+
# scripts (SEC-3). The `expect-send-credential` rule below exists because of
17+
# that miss. The default-deny promotion allowlist
18+
# (scripts/lib/public-allowlist.js), not this scanner, is the control that keeps
19+
# secrets out of the public snapshot.
20+
21+
[extend]
22+
useDefault = true
23+
24+
# --- Project-specific rules -------------------------------------------------
25+
26+
[[rules]]
27+
id = "expect-send-credential"
28+
description = "expect(1) script sending a literal credential — the SEC-3 shape the default ruleset misses"
29+
# NOTE: Go/RE2 has no lookahead. Instead of excluding command words, we require
30+
# the sent literal to contain NO whitespace — shell commands sent by expect
31+
# ("cat /root/x", "pm2 logs") always contain a space; a password rarely does.
32+
# Requires BOTH a digit and a punctuation character somewhere in the literal.
33+
# Command words sent by expect ("pm2reload", "restartservices") have neither;
34+
# passwords almost always have both. RE2 has no lookahead, so this is expressed
35+
# as alternation over the two orderings rather than two assertions.
36+
regex = '''send\s+\\{0,2}"{1,3}(?:[^"\s]*[0-9][^"\s]*[!-/:-@\[-`{-~][^"\s]*|[^"\s]*[!-/:-@\[-`{-~][^"\s]*[0-9][^"\s]*)\\{1,2}r"'''
37+
tags = ["credential", "expect", "SEC-3"]
38+
39+
[[rules]]
40+
id = "ssh-password-in-config"
41+
description = "plaintext password adjacent to an ssh/scp invocation in a config or tool-permission blob"
42+
# Value may contain spaces -- only the closing quote terminates it -- but must
43+
# LOOK like a credential: at least one digit and one punctuation character.
44+
# Without that, form-field declarations such as
45+
# password: { label: "Password", type: "password" }
46+
# match, and a rule that flags UI labels trains people to ignore it.
47+
regex = '''(?i)(sshpass\s+-p|password)\s*[=:]?\s*\\{0,2}"{1,3}(?:[^"\n]*[0-9][^"\n]*[!-/:-@\[-`{-~][^"\n]*|[^"\n]*[!-/:-@\[-`{-~][^"\n]*[0-9][^"\n]*)"'''
48+
tags = ["credential", "ssh", "SEC-3"]
49+
50+
[allowlist]
51+
description = "Values that are public by construction"
52+
53+
# Internal planning docs. These never publish (hardDeny blocks `plans/` in
54+
# scripts/lib/public-allowlist.js) and they DESCRIBE credential patterns in
55+
# prose — e.g. documenting the expect-style `send "<literal>\r"` shape that the
56+
# expect-send-credential rule above detects. That self-reference is the only
57+
# reason this path is listed. It is NOT a licence to store secrets here.
58+
# Not anchored with ^ deliberately: gitleaks reports ABSOLUTE paths when
59+
# --source points outside the repo root (as the promotion staging scan does),
60+
# so an anchored pattern silently fails to match.
61+
paths = [
62+
'''(^|/)plans/.*''',
63+
]
64+
65+
# Regexes for values that look like secrets but are public.
66+
regexes = [
67+
'''0x[0-9a-fA-F]{40}\b''', # 20-byte EVM addresses (public on-chain data)
68+
'''0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80''', # Anvil/Hardhat account #0 key — published in Foundry/Hardhat docs
69+
'''0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d''', # Anvil/Hardhat account #1 key — same
70+
]

.npmrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# hardhat (2.x) and @nomicfoundation/hardhat-ignition (3.x) have a peer-dep
2+
# mismatch on hardhat's major; ignition is not used by the MVP. Enable
3+
# legacy-peer-deps so a plain `npm install` works for newcomers.
4+
legacy-peer-deps=true

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22

CHANGELOG.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [1.0.0] — 2026-08-25 — MVP foundation
9+
10+
Initial public foundation of the T3 programmable fiat framework: an EIP-2535
11+
Diamond ERC-20 deposit token with programmable transfer envelopes and per-bank
12+
claim attribution, targeting a permissioned Hyperledger Besu consortium.
13+
14+
> Note: this is a foundation release, not a production-audited deployment. It has
15+
> no production history. See the README for current scope and the planned waves.
16+
17+
### Added
18+
- **Diamond core (EIP-2535):** proxy + DiamondCut/DiamondLoupe, manifest-driven
19+
facet registration (`scripts/lib/facet-manifest.js`) as the single source of
20+
truth for deploys, ABI generation, and the selector-collision / ABI-parity gates.
21+
- **ERC-20 deposit token:** base, pausable, direct transfer, mint/burn, fee logic,
22+
admin facets with isolated diamond storage per module.
23+
- **Programmable envelopes:** create / finalize / reverse / dispute lifecycle with
24+
configurable settlement type (CRYPTO_DIRECT, FIAT_INSTITUTIONAL) and expiration
25+
behavior (immediate, half-life decay, hold-until-manual, oracle-conditional,
26+
auto-reverse, dispute-hold). Includes SmartLock and envelope-inheritance facets.
27+
- **Per-bank claim attribution:** consortium mints route through
28+
`IssuanceAccountingLib.mintAttributed`; envelope finalization routes through
29+
`ClaimAttributionLib.finalizeEnvelopeClaims` + `substituteLiability` for
30+
cross-institution settlement. Activated via `initializeClaimAttribution`
31+
(requires zero supply at init).
32+
- **Consortium / banking:** multi-asset vault with factor-based collateral check
33+
(default 100% = 1:1; per-bank factors configurable), institution lifecycle /
34+
policy / registry, custodian registry, membership.
35+
- **Rules / compliance:** rules engine + config, automated emergency response
36+
(role-gated, fail-closed).
37+
- **Wallet recovery** state machine and **relayer fallback** (4-hour
38+
self-declaration) for ERC-2771 meta-transactions.
39+
- **Services:** Ponder event indexer, ERC-2771 meta-transaction relayer, and the
40+
settlement keeper (ships DISABLED and triple-gated).
41+
42+
### Changed
43+
- **Compliance arming observability (CF-R Obs-1):** the single `activeScopeCount`
44+
was split into per-control counters (`sanctionsScopeCount`, `kycScopeCount`,
45+
`cipScopeCount`, `travelRuleScopeCount`); `activeScopeCount()` remains as their
46+
sum and `complianceArmed()` reports any-armed. The legacy getters changed
47+
meaning: `isKycEnforceActive()` / `isCipEnforceActive()` /
48+
`isTravelRuleEnforceActive()` now report only the **network-scope** policy
49+
baseline, and `isScreeningEnforceActive()` reports whether any institution has
50+
per-institution sanctions enforcement enabled. Off-chain consumers that need
51+
"any scope armed" should migrate to the per-control `*ScopeCount()` views or
52+
`complianceArmed()`.
53+
- **Policy relax guard (CF-R Obs-2):** lowering an enforcement-class policy
54+
below its effective parent — including via `setNetworkPolicy` and via
55+
`clearInstitutionPolicy` / `clearWalletPolicy` of a tighter override — now
56+
requires `COMPLIANCE_EXEMPTION_ROLE` and emits `ComplianceExemptionGranted`.
57+
- **Escrow-creation recipient screening (K-F1):** `ESCROW_IN` compliance checks
58+
now screen the named recipient (payee-resolved through recovery) in addition
59+
to the sender. Cambio bearer notes (`to == address(0)`) remain exempt.
60+
- **Bulk recovery release gating (CF-2 core):** `applyBulkPolicy` ConfirmFiat
61+
and `resolveCambioNotesBulk` cancel/expire releases now run the
62+
`ESCROW_RELEASE` compliance gate against the resolved payee before value
63+
moves. Envelope reverse/clawback refund legs are deliberately not gated yet —
64+
they route to admin hold in the compliance-hold work (D2).
65+
- **Screening freshness enforcement (C-F9):** when sanctions are armed
66+
(`sanctionsScopeCount > 0`) and an admin has set `screeningStaleAfter > 0`,
67+
the sanctions precheck fails closed (`ComplianceScreeningStale`) for any
68+
checked party whose network screening is stale — including never-screened
69+
wallets (`lastScreenedAt == 0`), which is deliberately stricter than the
70+
informational `isScreeningStale()` view. The default window of 0 preserves
71+
prior behavior exactly.
72+
73+
### Security & hygiene
74+
- Tier-0 remediations: restricted permissionless metric updates, role-gated
75+
emergency deactivation, custody-takeover guard, recovery paths routed through
76+
the issuer-domain escrow release overload, fail-closed emergency tests.
77+
- Apache-2.0 license; Solidity SPDX headers retained pending owner decision;
78+
gitleaks configuration.
79+
80+
### Implemented but not production-activated
81+
- Wave 4: single-bank attributed issuance capacity (quote / reserve / execute) —
82+
`IssuanceControlFacet`, behind the `capacityModelActive` admin gate.
83+
- Wave 5: bilateral-net settlement cycle (open / propose / confirm / fund /
84+
finalize / fail) with replay-protected funding attestation —
85+
`SettlementCycleFacet`, behind the `settlementModelActive` admin gate.
86+
87+
### Not yet implemented
88+
- Multilateral-net CCP settlement — the documented scale endgame, gated on a
89+
future ADR and counsel review. ADR-003 covers the bilateral-net design that
90+
shipped; multilateral is explicitly out of scope for this release.

CODE_OF_CONDUCT.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Contributor Code of Conduct
2+
3+
## Our pledge
4+
5+
We as members, contributors, and maintainers pledge to make participation in our
6+
project a harassment-free experience for everyone, regardless of age, body size,
7+
visible or invisible disability, ethnicity, sex characteristics, gender identity
8+
and expression, level of experience, education, socio-economic status,
9+
nationality, personal appearance, race, religion, or sexual identity and
10+
orientation.
11+
12+
## Our standards
13+
14+
Examples of behavior that contributes to a positive environment:
15+
- Demonstrating empathy and kindness toward other people
16+
- Being respectful of differing opinions, viewpoints, and experiences
17+
- Giving and gracefully accepting constructive feedback
18+
- Accepting responsibility and apologizing to those affected by our mistakes
19+
20+
Examples of unacceptable behavior:
21+
- The use of sexualized language or imagery, and unwelcome sexual attention
22+
- Trolling, insulting or derogatory comments, and personal or political attacks
23+
- Public or private harassment
24+
- Publishing others' private information without explicit permission
25+
26+
## Enforcement
27+
28+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
29+
reported to the project maintainers. All complaints will be reviewed and
30+
investigated promptly and fairly. Maintainers are obligated to respect the
31+
privacy and security of the reporter of any incident.
32+
33+
## Attribution
34+
35+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
36+
version 2.1.

0 commit comments

Comments
 (0)