feat: Add presence heartbeat for Matrix online status
- matrix-gateway: POST /internal/matrix/presence/online endpoint - usePresenceHeartbeat hook with activity tracking - Auto away after 5 min inactivity - Offline on page close/visibility change - Integrated in MatrixChatRoom component
This commit is contained in:
30
backend/domain/dao/dao.logic.ts
Normal file
30
backend/domain/dao/dao.logic.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Pure domain logic for DAO operations
|
||||
* No I/O, no side effects
|
||||
*/
|
||||
|
||||
import type { DaoRecord, DaoLevel, FederationMode } from './types';
|
||||
|
||||
/**
|
||||
* Check if DAO can become a SuperDAO
|
||||
*/
|
||||
export function canBecomeSuperDao(dao: DaoRecord, childCount: number): boolean {
|
||||
return childCount >= 1 && dao.federationMode === 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if DAO can join a federation
|
||||
*/
|
||||
export function canJoinFederation(dao: DaoRecord, targetLevel: DaoLevel): boolean {
|
||||
// A3/A4 can join, exceptions for A2 handled by PDP
|
||||
return (dao.level === 'A3' || dao.level === 'A4') && dao.federationMode === 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if DAO can leave federation
|
||||
*/
|
||||
export function canLeaveFederation(dao: DaoRecord): boolean {
|
||||
return dao.federationMode === 'member' && dao.parentDaoId !== null;
|
||||
}
|
||||
|
||||
|
||||
37
backend/domain/dao/types.ts
Normal file
37
backend/domain/dao/types.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Domain types for DAO entities
|
||||
* Based on: microdao-architecture.md, superdao-federation.md
|
||||
*/
|
||||
|
||||
export type DaoLevel = 'A1' | 'A2' | 'A3' | 'A4';
|
||||
export type DaoType = 'platform' | 'public' | 'private';
|
||||
export type FederationMode = 'none' | 'member' | 'superdao';
|
||||
|
||||
export interface DaoRecord {
|
||||
daoId: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
level: DaoLevel;
|
||||
type: DaoType;
|
||||
parentDaoId?: string | null;
|
||||
federationMode: FederationMode;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface CreateDaoInput {
|
||||
name: string;
|
||||
description?: string;
|
||||
type: 'public' | 'private';
|
||||
level: 'A3' | 'A4';
|
||||
settings?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface CreatePlatformInput {
|
||||
name: string;
|
||||
slug: string;
|
||||
description?: string;
|
||||
domain?: string; // 'energy' | 'food' | 'water' | ...
|
||||
}
|
||||
|
||||
|
||||
38
backend/domain/pdp/policy.model.ts
Normal file
38
backend/domain/pdp/policy.model.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* PDP Policy Model
|
||||
* Based on: pdp_access.md, core-services-mvp.md
|
||||
*/
|
||||
|
||||
export type Decision = 'allow' | 'deny' | 'require-elevation';
|
||||
|
||||
export type PolicyId =
|
||||
| 'policy.dao.create'
|
||||
| 'policy.vendor.register'
|
||||
| 'policy.platform.create'
|
||||
| 'policy.federation.join'
|
||||
| 'policy.federation.leave'
|
||||
| 'policy.federation.create-superdao'
|
||||
| 'policy.federation.dissolve'
|
||||
| 'policy.agent.run';
|
||||
|
||||
export interface PdpContext {
|
||||
userId?: string;
|
||||
daoId?: string;
|
||||
daoLevel?: 'A1' | 'A2' | 'A3' | 'A4';
|
||||
// Additional context: roles, balances, staking, etc.
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface PdpRequest {
|
||||
policyId: PolicyId;
|
||||
resource: Record<string, unknown>;
|
||||
context: PdpContext;
|
||||
}
|
||||
|
||||
export interface PdpResponse {
|
||||
decision: Decision;
|
||||
reason?: string;
|
||||
details?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
|
||||
14
backend/domain/user/types.ts
Normal file
14
backend/domain/user/types.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Domain types for User
|
||||
*/
|
||||
|
||||
export type UserRole = 'owner' | 'admin' | 'member' | 'guest' | 'agent';
|
||||
|
||||
export interface User {
|
||||
userId: string;
|
||||
email?: string;
|
||||
name?: string;
|
||||
roles?: UserRole[];
|
||||
}
|
||||
|
||||
|
||||
27
backend/domain/wallet/types.ts
Normal file
27
backend/domain/wallet/types.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Domain types for Wallet
|
||||
* Based on: core-services-mvp.md, tokenomics/city-tokenomics.md
|
||||
*/
|
||||
|
||||
export type TokenSymbol = 'DAAR' | 'DAARION';
|
||||
|
||||
export interface Balance {
|
||||
symbol: TokenSymbol;
|
||||
amount: string; // Decimal as string to avoid precision issues
|
||||
}
|
||||
|
||||
export interface WalletBalances {
|
||||
userId: string;
|
||||
balances: Balance[];
|
||||
}
|
||||
|
||||
export interface AccessCheck {
|
||||
check: 'dao.create' | 'vendor.register' | 'platform.create';
|
||||
}
|
||||
|
||||
export interface AccessCheckResult {
|
||||
allowed: boolean;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user