add overall Gift Economies organization to this repo and refactor
This commit is contained in:
69
.cursor/rules/tech/README.mdc
Normal file
69
.cursor/rules/tech/README.mdc
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
alwaysApply: false
|
||||
---
|
||||
# Time Safari / Endorser Search Tech Ecosystem
|
||||
|
||||
> **Note**: For strategic planning and project vision, see the [main README](../../README.md) and [strategic planning docs](../../docs/). This file focuses on technical implementation details.
|
||||
|
||||
### Purpose
|
||||
|
||||
This describes the overall purpose and design across code repositories.
|
||||
|
||||
The Time Safari project (in the crowd-funder-for-time-pwa repository) is a front-end to make it intuitive and interesting to help people connect over activities. The intent is to enable people to find others with similar interests, to start activities and relationships via offers of help, and to encourage creative experiments for deeper and more widespread connections.
|
||||
|
||||
There are 3 kinds of actions in Time Safari:
|
||||
|
||||
- Gives, recognizing something given (whether time or physical goods) and the resulting impact
|
||||
|
||||
- Offers of help, to individuals or projects, which can be fulfilled by subsequent gives
|
||||
|
||||
- Projects, which aggregate offers and/or gives for a common purpose
|
||||
|
||||
The Endorser Server is an HTTP API service that allows recording of cryptographically signed assertions in a privacy-preserving fashion. Each participant chooses whether to allow any other participant to see their name attached to activity. The service is a convenient way to get basic functions; it is expected to provide direct P2P communications to support the same functionality for anyone who wants the alternative.
|
||||
|
||||
Web and mobile apps allow users to interact with the Endorser Server. The endorser-mobile project is a powerful interface but is not very user-friendly.
|
||||
|
||||
### Structure
|
||||
|
||||
The primary repos contain the majority of the functionality; the secondary repos are helpful but not absolutely necessary.
|
||||
|
||||
These repos are found on the local filesystem in the `repos` directory, ie. `../../repos` relative to this directory.
|
||||
|
||||
### Related Documentation
|
||||
|
||||
- **[Time Safari / Endorser Overview](../../tech/README-time-safari-endorser.md)** - High-level technical overview
|
||||
- **[Endorser.ch API Context](../../tech/README-endorser-context.md)** - Detailed API documentation
|
||||
- **[Active Projects & Tasks](../../tech/progress/)** - Current technical projects and tasks
|
||||
- **[Strategic Planning](../../docs/)** - Project vision and strategic planning documents
|
||||
|
||||
Primary Repos:
|
||||
|
||||
- endorser-ch is the back-end, written in Typescript
|
||||
|
||||
- crowd-funder-for-time-pwa is the front-end named Time Safari, written in Typescript with Vue & Vite, with deployments for mobile as well as web
|
||||
|
||||
Secondary Repos:
|
||||
|
||||
- image-api is a service for storing images, in Typescript
|
||||
|
||||
- py-push-server is a service to send push notifications
|
||||
|
||||
- lives-of-gifts is the website for the overall vision for humanity
|
||||
|
||||
- gifting-org-content is for design and other creative artifacts
|
||||
|
||||
- kickstarter-for-time is a playground to implement HTML designs that are subsequently moved into crowd-funder-for-time-pwa
|
||||
|
||||
- uport-demo is the web-facing front-end to explain the Endorser server
|
||||
|
||||
- endorser-docs is the documentation explaining the Endoser server design, in Restructured Text format
|
||||
|
||||
- time-safari-web is for the single pages at timesafari.org & timesafari.com
|
||||
|
||||
- endorser-mobile is the previous native app to talk to the Endorser server -- very powerful but harder to use
|
||||
|
||||
### Hosting
|
||||
|
||||
These repos are hosted by GitHub: endorser-ch, endorser-mobile, lives-of-gifts uport-demo, endorser-docs, time-safari-web
|
||||
|
||||
The remaining repos are hosted by gitea.anomalistdesign.com
|
||||
246
.cursor/rules/tech/endorser-service.mdc
Normal file
246
.cursor/rules/tech/endorser-service.mdc
Normal file
@@ -0,0 +1,246 @@
|
||||
---
|
||||
globs: repos/endorser-ch/src/**
|
||||
alwaysApply: false
|
||||
---
|
||||
# Endorser-ch Development Conventions
|
||||
|
||||
# Pagination Conventions
|
||||
|
||||
### Standard Pagination Parameters
|
||||
|
||||
### Required Pattern
|
||||
- **`beforeId`**: JWT ID to end before (exclusive) - primary pagination parameter
|
||||
- **`afterId`**: JWT ID to start after (exclusive) - used for feed-style results where newer items are needed
|
||||
|
||||
### Parameter Usage
|
||||
- **Routes**: Accept `beforeId` and `afterId` as query parameters
|
||||
- **Database methods**: Pass these parameters through to database layer
|
||||
- **Never use**: `limit`, `offset`, `page`, `skip`, or similar traditional pagination
|
||||
|
||||
### Limit
|
||||
- The limit is managed by the DB service, currently always set to DEFAULT_LIMIT
|
||||
|
||||
## API Route Implementation
|
||||
|
||||
### Query Parameter Handling
|
||||
```javascript
|
||||
// ✅ CORRECT - Use beforeId/afterId pattern
|
||||
const beforeId = req.query.beforeId
|
||||
const afterId = req.query.afterId
|
||||
dbService.methodByParamsPaged(params, afterId, beforeId)
|
||||
|
||||
// ❌ WRONG - Never use limit/offset
|
||||
const limit = parseInt(req.query.limit) || 50 // DON'T DO THIS
|
||||
const offset = parseInt(req.query.offset) || 0 // DON'T DO THIS
|
||||
```
|
||||
|
||||
### JSDoc Documentation Pattern
|
||||
```javascript
|
||||
/**
|
||||
* @param {string} beforeId.query.optional - the JWT ID of the entry before which to look (exclusive); by default, the last one is included
|
||||
* @param {string} afterId.query.optional - the JWT ID of the entry after which to look (exclusive); by default, the first one is included
|
||||
*/
|
||||
```
|
||||
|
||||
## Database Service Implementation
|
||||
|
||||
### Method Signature Pattern
|
||||
```javascript
|
||||
// ✅ CORRECT - Standard pagination signature
|
||||
methodByParamsPaged(params, afterIdInput, beforeIdInput) {
|
||||
// Implementation using JWT ID comparisons
|
||||
}
|
||||
|
||||
// ❌ WRONG - Never use limit/offset in method signatures
|
||||
methodByParamsPaged(params, limit, offset) { // DON'T DO THIS
|
||||
```
|
||||
|
||||
### SQL Implementation
|
||||
```javascript
|
||||
// ✅ CORRECT - Use JWT ID comparisons
|
||||
let sql = "SELECT * FROM table WHERE conditions"
|
||||
if (afterIdInput) {
|
||||
params.push(afterIdInput)
|
||||
sql += " AND jwtId > ?"
|
||||
}
|
||||
if (beforeIdInput) {
|
||||
params.push(beforeIdInput)
|
||||
sql += " AND jwtId < ?"
|
||||
}
|
||||
sql += " ORDER BY jwtId DESC LIMIT " + DEFAULT_LIMIT
|
||||
|
||||
// ❌ WRONG - Never use OFFSET
|
||||
sql += " LIMIT ? OFFSET ?" // DON'T DO THIS
|
||||
```
|
||||
|
||||
### Response Format
|
||||
```javascript
|
||||
// ✅ CORRECT - Standard response format
|
||||
const result = {
|
||||
data: processedResults,
|
||||
hitLimit: results.length === DEFAULT_LIMIT
|
||||
}
|
||||
|
||||
// ❌ WRONG - Don't include limit/offset metadata
|
||||
const result = {
|
||||
data: results,
|
||||
limit: 50, // DON'T DO THIS
|
||||
offset: 100 // DON'T DO THIS
|
||||
}
|
||||
```
|
||||
|
||||
## Consistent Patterns Across Codebase
|
||||
|
||||
### Why This Pattern?
|
||||
1. **Consistency**: JWT IDs provide stable, chronological ordering
|
||||
2. **Performance**: Index-based lookups are faster than OFFSET
|
||||
3. **Reliability**: Results don't shift when new records are added
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
When creating new paginated endpoints:
|
||||
|
||||
- Use `beforeId`/`afterId` query parameters in routes
|
||||
- Pass these parameters to database methods as `afterIdInput`/`beforeIdInput`
|
||||
- Use JWT ID comparisons (`jwtId > ?`, `jwtId < ?`) in SQL
|
||||
- Include `DEFAULT_LIMIT` constant in SQL for consistent limits
|
||||
- Return `{ data: [], hitLimit: boolean }` response format
|
||||
- Document parameters with standard JSDoc format
|
||||
- Never use `limit`, `offset`, `page`, or similar parameters
|
||||
|
||||
# Database Migration Documentation
|
||||
|
||||
## CRITICAL: Always Update sql/README.md
|
||||
|
||||
**Every database migration MUST be documented in `sql/README.md`** because migration files cannot be edited after flyway has run.
|
||||
|
||||
## Migration Documentation Process
|
||||
|
||||
When creating a new migration file (e.g., `V18__new_feature.sqlite3`):
|
||||
|
||||
1. **Create the migration file** with proper SQL schema changes
|
||||
2. **Immediately update `sql/README.md`** with the new schema
|
||||
3. **Add explanatory comments** for complex fields or relationships
|
||||
4. **Update indexes** documentation if new indexes are created
|
||||
|
||||
## Schema Update Checklist
|
||||
|
||||
When creating a migration:
|
||||
|
||||
- [ ] Create migration file with proper version number (VXX__description.sqlite3)
|
||||
- [ ] Add comprehensive SQL comments in migration file
|
||||
- [ ] Update sql/README.md with complete table schema
|
||||
- [ ] Document all new indexes in README.md
|
||||
- [ ] Explain field purposes and constraints
|
||||
- [ ] Verify README.md reflects current schema state
|
||||
- [ ] Test migration on development database
|
||||
|
||||
## Why This Documentation Matters
|
||||
|
||||
1. **Flyway Immutability**: Migration files cannot be edited after deployment
|
||||
2. **Schema Clarity**: README.md provides the definitive current schema
|
||||
3. **Developer Onboarding**: New developers need clear schema documentation
|
||||
4. **Maintenance**: Future changes require understanding current structure
|
||||
|
||||
# Data Privacy and DID Hiding
|
||||
|
||||
## hideDidsAndAddLinksToNetwork Function
|
||||
|
||||
The `hideDidsAndAddLinksToNetwork` function is a critical security component that ensures searches for DIDs (Decentralized Identifiers) only show results that are visible to users who have proper permissions to see them.
|
||||
|
||||
### Purpose
|
||||
|
||||
This function processes API response data to:
|
||||
1. **Hide DIDs** that the requesting user doesn't have permission to see
|
||||
2. **Add network links** showing which DIDs in the user's network can see hidden data
|
||||
3. **Include public URLs** for DIDs that have published public profiles
|
||||
4. **Validate search terms** to prevent data leakage through search queries
|
||||
|
||||
### Function Signatures
|
||||
|
||||
```javascript
|
||||
// Primary function
|
||||
async function hideDidsAndAddLinksToNetwork(requesterDid, inputData, searchTerms)
|
||||
|
||||
// Wrapper for responses with a "data" key
|
||||
async function hideDidsAndAddLinksToNetworkInDataKey(requesterDid, input, searchTerms)
|
||||
```
|
||||
|
||||
### Critical searchTerms Parameter
|
||||
|
||||
**SECURITY REQUIREMENT**: The `searchTerms` parameter MUST contain all user-provided query data (since it might include DIDs or parts of DIDs).
|
||||
|
||||
#### Why searchTerms is Required
|
||||
|
||||
The function validates that after hiding DIDs, all search terms are still visible in the result. This prevents users from:
|
||||
- Searching for a DID they can't see and getting results that reveal its existence
|
||||
- Using partial DID strings to probe for hidden data
|
||||
- Discovering private information through search inference
|
||||
|
||||
#### Implementation Pattern
|
||||
|
||||
```javascript
|
||||
// ✅ CORRECT - Include all user query parameters that might contain DIDs
|
||||
const searchTermMayBeDIDs = [
|
||||
req.query.claimContents,
|
||||
req.query.issuer,
|
||||
req.query.subject,
|
||||
req.query.handleId
|
||||
]
|
||||
dbService.someMethod(params)
|
||||
.then(results => hideDidsAndAddLinksToNetwork(
|
||||
res.locals.authTokenIssuer,
|
||||
results,
|
||||
searchTermMayBeDIDs
|
||||
))
|
||||
|
||||
// ❌ WRONG - Empty array when user provided search terms
|
||||
.then(results => hideDidsAndAddLinksToNetwork(
|
||||
res.locals.authTokenIssuer,
|
||||
results,
|
||||
[] // DON'T DO THIS if user provided searchable parameters
|
||||
))
|
||||
```
|
||||
|
||||
### Usage Guidelines
|
||||
|
||||
#### When to Use Empty searchTerms Array
|
||||
|
||||
Use `[]` only when:
|
||||
- No user input was used to filter the results
|
||||
- The endpoint doesn't accept search parameters
|
||||
- You're certain no DIDs could be in the query parameters
|
||||
|
||||
#### When to Include Search Terms
|
||||
|
||||
Always include search terms when:
|
||||
- User provided `claimContents`, `issuer`, `subject`, `handleId` parameters
|
||||
- Any text search functionality is involved
|
||||
- User input could contain DIDs or partial DIDs
|
||||
- The query filters data based on user-provided strings
|
||||
|
||||
### Security Checklist
|
||||
|
||||
When implementing endpoints, always consider usage of `hideDidsAndAddLinksToNetwork`:
|
||||
|
||||
- [ ] Use it for almost every endpoint, and exceptions should be vetted and documented
|
||||
- [ ] Identify all user-provided query parameters
|
||||
- [ ] Include any parameter that could contain DIDs in `searchTerms`
|
||||
- [ ] Include any text search parameters in `searchTerms`
|
||||
- [ ] Use empty array `[]` only when no user input affects the query
|
||||
- [ ] Test that search results don't leak hidden DID information
|
||||
- [ ] Verify that partial DID searches are properly filtered
|
||||
|
||||
### Error Prevention
|
||||
|
||||
**Red Flags** - These patterns indicate potential security issues:
|
||||
- Using `[]` for searchTerms when user provided search parameters
|
||||
- Not including text search fields in searchTerms
|
||||
- Forgetting to include DID-related query parameters
|
||||
- Bypassing the function for "simple" endpoints that still return DID data
|
||||
|
||||
**Green Flags** - These patterns indicate proper usage:
|
||||
- Including all user query parameters that might contain DIDs
|
||||
- Using `[]` only for endpoints with no user search input
|
||||
- Consistent application across all endpoints returning DID data
|
||||
- Proper testing of search result filtering
|
||||
92
.cursor/rules/tech/node-express.mdc
Normal file
92
.cursor/rules/tech/node-express.mdc
Normal file
@@ -0,0 +1,92 @@
|
||||
---
|
||||
description: Node.js and Express.js best practices for backend development
|
||||
globs: repos/endorser-ch/src/**
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Node.js and Express.js Best Practices
|
||||
|
||||
## Project Structure
|
||||
- Use proper directory structure
|
||||
- Implement proper module organization
|
||||
- Use proper middleware organization
|
||||
- Keep routes organized by domain
|
||||
- Implement proper error handling
|
||||
- Use proper configuration management
|
||||
|
||||
## Express Setup
|
||||
- Use proper middleware setup
|
||||
- Implement proper routing
|
||||
- Use proper error handling
|
||||
- Configure proper security middleware
|
||||
- Implement proper validation
|
||||
- Use proper static file serving
|
||||
|
||||
## API Design
|
||||
- Use proper REST principles
|
||||
- Implement proper versioning
|
||||
- Use proper request validation
|
||||
- Handle errors properly
|
||||
- Implement proper response formats
|
||||
- Document APIs properly
|
||||
|
||||
- Use JWT ID-based cursor pagination (beforeId/afterId) - NEVER use limit/offset pagination (see endorser-pagination.mdc)
|
||||
|
||||
## Database Integration
|
||||
- Use proper ORM/ODM
|
||||
- Implement proper migrations
|
||||
- Use proper connection pooling
|
||||
- Implement proper transactions
|
||||
- Use proper query optimization
|
||||
- Handle database errors properly
|
||||
|
||||
- Implement JWT ID-based cursor pagination in database methods - NEVER use LIMIT/OFFSET patterns
|
||||
- Always update sql/README.md when creating migrations (see endorser-pagination.mdc)
|
||||
|
||||
## Authentication
|
||||
- Implement proper JWT handling
|
||||
- Use proper password hashing
|
||||
- Implement proper session management
|
||||
- Use proper OAuth integration
|
||||
- Implement proper role-based access
|
||||
- Handle auth errors properly
|
||||
|
||||
## Security
|
||||
- Use proper CORS setup
|
||||
- Implement proper rate limiting
|
||||
- Use proper security headers
|
||||
- Implement proper input validation
|
||||
- Use proper encryption
|
||||
- Handle security vulnerabilities
|
||||
|
||||
## Performance
|
||||
- Use proper caching
|
||||
- Implement proper async operations
|
||||
- Use proper connection pooling
|
||||
- Implement proper logging
|
||||
- Use proper monitoring
|
||||
- Handle high traffic properly
|
||||
|
||||
## Testing
|
||||
- Write proper unit tests
|
||||
- Implement proper integration tests
|
||||
- Use proper test runners
|
||||
- Implement proper mocking
|
||||
- Test error scenarios
|
||||
- Use proper test coverage
|
||||
|
||||
## Deployment
|
||||
- Use proper Docker setup
|
||||
- Implement proper CI/CD
|
||||
- Use proper environment variables
|
||||
- Configure proper logging
|
||||
- Implement proper monitoring
|
||||
- Handle deployment errors
|
||||
|
||||
## Best Practices
|
||||
- Follow Node.js best practices
|
||||
- Use proper async/await
|
||||
- Implement proper error handling
|
||||
- Use proper logging
|
||||
- Handle process signals properly
|
||||
- Document code properly
|
||||
58
.cursor/rules/tech/typescript.mdc
Normal file
58
.cursor/rules/tech/typescript.mdc
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
description: TypeScript coding standards and best practices for modern web development
|
||||
globs: **/*.ts,repos/crowd-funder-for-time-pwa/src/**/*.ts
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# TypeScript Best Practices
|
||||
|
||||
## Type System
|
||||
- Prefer interfaces over types for object definitions
|
||||
- Use type for unions, intersections, and mapped types
|
||||
- Avoid using `any`, prefer `unknown` for unknown types
|
||||
- Use strict TypeScript configuration
|
||||
- Leverage TypeScript's built-in utility types
|
||||
- Use generics for reusable type patterns
|
||||
|
||||
## Naming Conventions
|
||||
- Use PascalCase for type names and interfaces
|
||||
- Use camelCase for variables and functions
|
||||
- Use UPPER_CASE for constants
|
||||
- Use descriptive names with auxiliary verbs (e.g., isLoading, hasError)
|
||||
- Prefix interfaces for React props with 'Props' (e.g., ButtonProps)
|
||||
|
||||
## Code Organization
|
||||
- Keep type definitions close to where they're used
|
||||
- Export types and interfaces from dedicated type files when shared
|
||||
- Use barrel exports (index.ts) for organizing exports
|
||||
- Place shared types in a `types` directory
|
||||
- Co-locate component props with their components
|
||||
|
||||
## Functions
|
||||
- Use explicit return types for public functions
|
||||
- Use arrow functions for callbacks and methods
|
||||
- Implement proper error handling with custom error types
|
||||
- Use function overloads for complex type scenarios
|
||||
- Prefer async/await over Promises
|
||||
|
||||
## Best Practices
|
||||
- Enable strict mode in tsconfig.json
|
||||
- Use readonly for immutable properties
|
||||
- Leverage discriminated unions for type safety
|
||||
- Use type guards for runtime type checking
|
||||
- Implement proper null checking
|
||||
- Avoid type assertions unless necessary
|
||||
|
||||
## Error Handling
|
||||
- Create custom error types for domain-specific errors
|
||||
- Use Result types for operations that can fail
|
||||
- Implement proper error boundaries
|
||||
- Use try-catch blocks with typed catch clauses
|
||||
- Handle Promise rejections properly
|
||||
|
||||
## Patterns
|
||||
- Use the Builder pattern for complex object creation
|
||||
- Implement the Repository pattern for data access
|
||||
- Use the Factory pattern for object creation
|
||||
- Leverage dependency injection
|
||||
- Use the Module pattern for encapsulation
|
||||
87
.cursor/rules/tech/vue.mdc
Normal file
87
.cursor/rules/tech/vue.mdc
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
description: Vue.js best practices and patterns for modern web applications
|
||||
globs: **/*.vue,repos/crowd-funder-for-time-pwa/src/**/*.vue
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Vue.js Best Practices
|
||||
|
||||
## Component Structure
|
||||
- Use Composition API over Options API
|
||||
- Keep components small and focused
|
||||
- Use proper TypeScript integration
|
||||
- Implement proper props validation
|
||||
- Use proper emit declarations
|
||||
- Keep template logic minimal
|
||||
|
||||
## Composition API
|
||||
- Use proper ref and reactive
|
||||
- Implement proper lifecycle hooks
|
||||
- Use composables for reusable logic
|
||||
- Keep setup function clean
|
||||
- Use proper computed properties
|
||||
- Implement proper watchers
|
||||
|
||||
## State Management
|
||||
- Use Pinia for state management
|
||||
- Keep stores modular
|
||||
- Use proper state composition
|
||||
- Implement proper actions
|
||||
- Use proper getters
|
||||
- Handle async state properly
|
||||
|
||||
## Performance
|
||||
- Use proper component lazy loading
|
||||
- Implement proper caching
|
||||
- Use proper computed properties
|
||||
- Avoid unnecessary watchers
|
||||
- Use proper v-show vs v-if
|
||||
- Implement proper key management
|
||||
|
||||
## Routing
|
||||
- Use Vue Router properly
|
||||
- Implement proper navigation guards
|
||||
- Use proper route meta fields
|
||||
- Handle route params properly
|
||||
- Implement proper lazy loading
|
||||
- Use proper navigation methods
|
||||
|
||||
## Forms
|
||||
- Use v-model properly
|
||||
- Implement proper validation
|
||||
- Handle form submission properly
|
||||
- Show proper loading states
|
||||
- Use proper error handling
|
||||
- Implement proper form reset
|
||||
|
||||
## TypeScript Integration
|
||||
- Use proper component type definitions
|
||||
- Implement proper prop types
|
||||
- Use proper emit declarations
|
||||
- Handle proper type inference
|
||||
- Use proper composable types
|
||||
- Implement proper store types
|
||||
|
||||
## Testing
|
||||
- Write proper unit tests
|
||||
- Implement proper component tests
|
||||
- Use Vue Test Utils properly
|
||||
- Test composables properly
|
||||
- Implement proper mocking
|
||||
- Test async operations
|
||||
|
||||
## Best Practices
|
||||
- Follow Vue style guide
|
||||
- Use proper naming conventions
|
||||
- Keep components organized
|
||||
- Implement proper error handling
|
||||
- Use proper event handling
|
||||
- Document complex logic
|
||||
|
||||
## Build and Tooling
|
||||
- Use Vite for development
|
||||
- Configure proper build setup
|
||||
- Use proper environment variables
|
||||
- Implement proper code splitting
|
||||
- Use proper asset handling
|
||||
- Configure proper optimization
|
||||
Reference in New Issue
Block a user