Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

274 changes: 274 additions & 0 deletions PR_SUMMARY_DESIGN_SYSTEM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
# PR Summary: Design System & ZK Proof Aggregation

This PR implements four features:

1. **Modal/Dialog Component** - Accessible, themeable modal for the design system
2. **Form Fields + Validation States** - Form inputs wired to Zod validation
3. **Recursive Proof Aggregation** - ZK proof batching for cost-efficient verification
4. **Terms/Consent Audit Trail** - Versioned consent with tamper-evident hash chain

---

## 1. Modal / Dialog Component

### Files Created
- `frontend/src/components/ui/Modal.jsx` - Modal and ConfirmDialog components
- `frontend/src/components/ui/Modal.css` - Styling with design system tokens
- `frontend/src/stories/Modal.stories.jsx` - Storybook documentation
- `frontend/src/components/ui/__tests__/Modal.test.jsx` - Unit tests

### Acceptance Criteria Met
- [x] **Focus trap** - Tab/Shift+Tab cycle within modal; focus returns to trigger on close
- [x] **ESC/overlay close** - Escape key and overlay click dismiss modal
- [x] **Async confirm state** - Loading indicator for async operations
- [x] **Storybook story + visual snapshot** - Multiple stories including async confirm
- [x] **Keyboard + screen-reader accessible** - `aria-modal`, `aria-labelledby`, `aria-describedby`, roving focus

### Usage
```jsx
import { Modal, ConfirmDialog } from '../components/ui';

// Basic modal
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} title="Confirm Action">
<p>Are you sure?</p>
<Modal.Actions>
<Button onClick={() => setIsOpen(false)}>Cancel</Button>
<Button onClick={handleConfirm}>Confirm</Button>
</Modal.Actions>
</Modal>

// Async confirm
<ConfirmDialog
isOpen={isOpen}
onClose={() => setIsOpen(false)}
onConfirm={async () => { /* ... */ }}
title="Delete Campaign?"
message="This action cannot be undone."
loading={isLoading}
/>
```

---

## 2. Form Fields + Validation States Component

### Files Created
- `frontend/src/components/ui/FormField.jsx` - Input, select, textarea with validation
- `frontend/src/components/ui/FormField.css` - Validation state styling
- `frontend/src/stories/FormField.stories.jsx` - Storybook documentation
- `frontend/src/components/ui/__tests__/FormField.test.jsx` - Unit tests

### Acceptance Criteria Met
- [x] **Text/number/select with error states** - All input types supported
- [x] **Wired to validation library** - `useFormValidation` hook integrates with Zod
- [x] **Storybook story + visual snapshot** - Multiple stories with validation demos
- [x] **Keyboard + screen-reader accessible** - `aria-invalid`, `aria-describedby`, error role="alert"

### Usage
```jsx
import FormField, { useFormValidation } from '../components/ui/FormField';

// Basic field
<FormField
type="text"
label="Campaign Name"
name="name"
value={values.name}
onChange={handleChange}
error={errors.name}
required
/>

// With Zod validation
const { values, errors, handleChange, handleSubmit } = useFormValidation({
schema: campaignCreateSchema,
initialValues: { name: '', rewardPerAction: 0 },
onSubmit: async (values) => { /* ... */ },
});

return (
<form onSubmit={handleSubmit}>
<FormField label="Name" name="name" value={values.name} onChange={handleChange} error={errors.name?.message} />
</form>
);
```

---

## 3. Recursive Proof Aggregation for Batched Private Claims

### Files Created
- `backend/src/services/proofAggregation.js` - Proof aggregator prototype
- `backend/src/services/proofAggregation.test.js` - Unit tests
- `docs/PROOF_AGGREGATION_FEASIBILITY.md` - Feasibility study with cost analysis

### Acceptance Criteria Met
- [x] **Feasibility documented with cost analysis** - Comprehensive document showing 98%+ gas savings
- [x] **Prototype aggregates N proofs into one verification** - Binary tree aggregation implemented

### Cost Analysis
| Claims | Without Aggregation | With Aggregation | Savings |
|--------|-------------------|------------------|---------|
| 10 | 2,500,000 gas | 330,000 gas | 86.8% |
| 100 | 25,000,000 gas | 330,000 gas | 98.7% |
| 1,000 | 250,000,000 gas | 600,000 gas | 99.8% |

### Architecture
```
Proof 1 ─┐
Proof 2 ─┤
Proof 3 ─┼→ Aggregation Circuit → Aggregated Proof → On-chain Verification
Proof 4 ─┤
... │
Proof N ─┘
```

### Usage
```javascript
import { ProofAggregator, BatchClaimProcessor } from './services/proofAggregation.js';

const aggregator = new ProofAggregator();
const aggregated = await aggregator.aggregate([proof1, proof2, proof3, proof4]);
const isValid = await aggregator.verifyAggregated(aggregated);

// Process batch
const processor = new BatchClaimProcessor();
const result = await processor.processBatch(claims);
// result.gasEstimate.savings = "98.7%"
```

---

## 4. Terms/Consent + Audit Trail for Policy Acceptance

### Files Created
- `backend/src/services/consentService.js` - Versioned consent with hash chain
- `backend/src/services/consentService.test.js` - Unit tests
- `backend/src/db/migrations/018_consent_audit_trail.js` - Database migration
- `frontend/src/components/TermsConsent.jsx` - UI component
- `frontend/src/components/TermsConsent.css` - Styling

### Acceptance Criteria Met
- [x] **Versioned consent recorded per user** - Terms versions with content hash
- [x] **Tamper-evident (hash-chained) trail** - SHA-256 chain with integrity verification
- [x] **Exportable** - CSV and JSON export of audit trail

### Database Schema
```sql
CREATE TABLE terms_versions (
id INTEGER PRIMARY KEY,
version TEXT UNIQUE,
content_hash TEXT NOT NULL,
content TEXT NOT NULL,
published_at TEXT,
is_current INTEGER DEFAULT 0
);

CREATE TABLE user_consent (
id INTEGER PRIMARY KEY,
user_id TEXT NOT NULL,
terms_version TEXT NOT NULL,
consent_type TEXT DEFAULT 'terms',
accepted_at TEXT,
ip_address TEXT,
user_agent TEXT,
metadata TEXT
);

CREATE TABLE consent_audit_trail (
id INTEGER PRIMARY KEY,
seq INTEGER UNIQUE,
user_id TEXT NOT NULL,
action TEXT NOT NULL,
terms_version TEXT,
prev_hash TEXT NOT NULL,
entry_hash TEXT NOT NULL,
timestamp TEXT,
metadata TEXT
);
```

### Usage
```javascript
import { createConsentService } from './services/consentService.js';

const consent = createConsentService({ db });

// Record consent
await consent.recordConsent(userId, 'v1.0.0', {
ipAddress: '127.0.0.1',
userAgent: 'Mozilla/5.0...'
});

// Check acceptance
const accepted = consent.hasAcceptedCurrentTerms(userId);

// Verify integrity
const { valid } = consent.verifyAuditTrailIntegrity();

// Export
const csv = consent.exportAsCsv({ userId });
const json = consent.exportAsJson({ userId });
```

---

## Testing Summary

### Frontend Tests
```
✓ src/components/ui/__tests__/Modal.test.jsx (15 tests)
✓ src/components/ui/__tests__/FormField.test.jsx (18 tests)
Total: 33 tests passed
```

### Backend Tests
```
✓ proofAggregation.test.js (9 tests)
✓ consentService.test.js (12 tests)
```

### Build Verification
```
✓ Frontend build successful (47.16s)
✓ Storybook build successful (1.25 min)
```

---

## Files Changed Summary

### New Files (19)
- `frontend/src/components/ui/Modal.jsx`
- `frontend/src/components/ui/Modal.css`
- `frontend/src/components/ui/FormField.jsx`
- `frontend/src/components/ui/FormField.css`
- `frontend/src/stories/Modal.stories.jsx`
- `frontend/src/stories/FormField.stories.jsx`
- `frontend/src/components/ui/__tests__/Modal.test.jsx`
- `frontend/src/components/ui/__tests__/FormField.test.jsx`
- `frontend/src/components/TermsConsent.jsx`
- `frontend/src/components/TermsConsent.css`
- `backend/src/services/proofAggregation.js`
- `backend/src/services/proofAggregation.test.js`
- `backend/src/services/consentService.js`
- `backend/src/services/consentService.test.js`
- `backend/src/db/migrations/018_consent_audit_trail.js`
- `docs/PROOF_AGGREGATION_FEASIBILITY.md`

### Modified Files (2)
- `frontend/src/components/ui/index.js` - Added Modal and FormField exports
- `frontend/src/lib/apiClient.js` - Added consent API methods

---

## Checklist

- [x] All acceptance criteria met
- [x] Unit tests passing
- [x] Build successful
- [x] Storybook stories created
- [x] Keyboard accessible
- [x] Screen-reader accessible
- [x] Themeable (dark/light)
- [x] Documentation complete
6 changes: 3 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@opentelemetry/sdk-node": "^0.55.0",
"@opentelemetry/semantic-conventions": "^1.28.0",
"@stellar/stellar-sdk": "^14.0.0",
"better-sqlite3": "^11.0.0",
"better-sqlite3": "^11.10.0",
"compression": "^1.8.0",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
Expand All @@ -50,8 +50,6 @@
},
"devDependencies": {
"@eslint/js": "^9.0.0",
"eslint": "^9.0.0",
"globals": "^15.0.0",
"@readme/openapi-parser": "^2.6.0",
"@redocly/cli": "^1.34.5",
"@types/cors": "^2.8.0",
Expand All @@ -60,6 +58,8 @@
"@types/supertest": "^6.0.0",
"ajv": "^8.17.0",
"ajv-formats": "^3.0.1",
"eslint": "^9.0.0",
"globals": "^15.0.0",
"js-yaml": "^4.1.0",
"nodemon": "^3.1.0",
"redoc-cli": "^0.13.21",
Expand Down
Loading