feat(apps): Add Apps subsystem: App and AppConnection models, managers, typed request handlers, web UI routes and documentation

This commit is contained in:
2025-12-01 09:18:48 +00:00
parent f54588e877
commit 6b04c529da
28 changed files with 1491 additions and 21 deletions
+9 -5
View File
@@ -7,8 +7,8 @@ This directory contains user stories for the idp.global Identity Provider platfo
```
stories/
├── end-user/ # Stories for regular users (8)
├── organization-owner/ # Stories for organization admins (8)
├── developer/ # Stories for API/SDK consumers (7)
├── organization-owner/ # Stories for organization admins (11)
├── developer/ # Stories for API/SDK consumers (8)
└── admin/ # Stories for platform administrators (7)
```
@@ -37,6 +37,9 @@ stories/
| ORG-006 | [Configure SSO for Organization](organization-owner/ORG-006-sso-config.md) | High | New |
| ORG-007 | [View Organization Audit Logs](organization-owner/ORG-007-audit-logs.md) | Medium | New |
| ORG-008 | [Manage Subscription and Billing](organization-owner/ORG-008-subscription-management.md) | Medium | Enhance |
| ORG-009 | [Connect Global Apps](organization-owner/ORG-009-global-apps.md) | High | New |
| ORG-010 | [Browse and Install Partner Apps](organization-owner/ORG-010-app-store.md) | Medium | New |
| ORG-011 | [Create Custom OIDC Apps](organization-owner/ORG-011-custom-oidc-apps.md) | Medium | New |
### Developer (DEV)
| ID | Title | Priority | Source |
@@ -48,6 +51,7 @@ stories/
| DEV-005 | [Register OAuth Client App](developer/DEV-005-oauth-client.md) | Medium | New |
| DEV-006 | [Understand API Rate Limits](developer/DEV-006-rate-limiting.md) | Low | New |
| DEV-007 | [Validate JWTs in My Application](developer/DEV-007-jwt-validation.md) | Medium | Enhance |
| DEV-008 | [Submit App to AppStore](developer/DEV-008-submit-partner-app.md) | Low | New |
### Platform Admin (ADM)
| ID | Title | Priority | Source |
@@ -65,9 +69,9 @@ stories/
| Priority | Count | Stories |
|----------|-------|---------|
| Critical | 3 | EU-002, ORG-002, ADM-001 |
| High | 10 | EU-001, EU-004, ORG-001, ORG-003, ORG-006, DEV-001, DEV-002, DEV-004, ADM-002, ADM-003 |
| Medium | 12 | EU-003, EU-005, EU-006, ORG-004, ORG-005, ORG-007, ORG-008, DEV-003, DEV-005, DEV-007, ADM-004, ADM-005, ADM-007 |
| Low | 5 | EU-007, EU-008, DEV-006, ADM-006 |
| High | 11 | EU-001, EU-004, ORG-001, ORG-003, ORG-006, ORG-009, DEV-001, DEV-002, DEV-004, ADM-002, ADM-003 |
| Medium | 14 | EU-003, EU-005, EU-006, ORG-004, ORG-005, ORG-007, ORG-008, ORG-010, ORG-011, DEV-003, DEV-005, DEV-007, ADM-004, ADM-005, ADM-007 |
| Low | 6 | EU-007, EU-008, DEV-006, DEV-008, ADM-006 |
## Source Legend
@@ -0,0 +1,130 @@
# Manage Global Apps
**ID:** ADM-008
**Priority:** High
**Status:** In Development
**Phase:** 1
## User Story
As a global administrator, I want to create, configure, and manage first-party global apps (foss.global, task.vc, etc.) so that organization owners can connect to these integrated services.
## Acceptance Criteria
- [ ] Only users with `isGlobalAdmin: true` can access the admin page
- [ ] View list of all global apps with their status
- [ ] Create new global apps with OAuth credentials
- [ ] Edit existing global app details (name, description, logo, URLs)
- [ ] Activate/deactivate global apps (inactive apps hidden from org owners)
- [ ] View connection statistics per app (how many orgs connected)
- [ ] Regenerate OAuth client credentials for an app
- [ ] Delete global apps (with confirmation and impact warning)
- [ ] Admin page accessible at `/admin` route
## Technical Notes
- Global admin flag stored on user: `isGlobalAdmin: boolean`
- Separate from organization roles (platform-level permission)
- OAuth credentials generated server-side, secrets never exposed in full
- App deletion should warn about existing connections
- Audit logging for all admin actions
## Data Model
```typescript
interface IUser {
id: string;
data: {
// ... existing fields ...
isGlobalAdmin?: boolean; // Platform-level admin flag
};
}
interface IGlobalApp {
id: string;
type: 'global';
data: {
name: string;
description: string;
logoUrl: string;
appUrl: string;
oauthCredentials: IOAuthCredentials;
isActive: boolean;
category: string;
createdAt: number;
createdByUserId: string;
};
}
```
## Request Interfaces
```typescript
interface IReq_CreateGlobalApp {
method: 'createGlobalApp';
request: {
jwt: string;
name: string;
description: string;
logoUrl: string;
appUrl: string;
category: string;
redirectUris: string[];
allowedScopes: string[];
};
response: {
app: IGlobalApp;
clientSecret: string; // Only shown once on creation
};
}
interface IReq_UpdateGlobalApp {
method: 'updateGlobalApp';
request: {
jwt: string;
appId: string;
updates: Partial<IGlobalApp['data']>;
};
response: {
app: IGlobalApp;
};
}
interface IReq_DeleteGlobalApp {
method: 'deleteGlobalApp';
request: {
jwt: string;
appId: string;
};
response: {
success: boolean;
disconnectedOrganizations: number;
};
}
interface IReq_GetGlobalAppStats {
method: 'getGlobalAppStats';
request: {
jwt: string;
};
response: {
apps: Array<{
app: IGlobalApp;
connectionCount: number;
}>;
};
}
```
## UI Components
- **GlobalAdminView** (`/admin`) - Main admin dashboard
- **Global Apps Tab** - List of global apps with CRUD operations
- **Create/Edit App Dialog** - Form for app configuration
- Navigation shows "Admin" link only for global admins
## Security Considerations
- Server-side validation of `isGlobalAdmin` flag on all admin endpoints
- JWT must be validated and user's admin status checked
- Rate limiting on credential regeneration
- Audit trail for all changes
## Related Stories
- ORG-009: Connect Global Apps (organization perspective)
- ADM-003: Platform-wide Audit Logging
+19 -3
View File
@@ -19,10 +19,26 @@ As a developer, I want to properly register my application with a unique App ID
## Technical Notes
- Current client has `id: ''` placeholder (TODO in code)
- Need Application model in database
- App credentials similar to OAuth client credentials
- App ID is now part of the unified Apps model (`IApp` discriminated union)
- Three app types exist: Global Apps, Partner Apps, Custom OIDC Apps
- For custom applications, use the Custom OIDC Apps flow (ORG-011)
- App credentials stored as `IOAuthCredentials` with hashed client secret
- Validate redirect URIs to prevent open redirector attacks
- App ID should be included in JWT claims
- App ID/Client ID is included in JWT claims
## Apps Architecture
The Apps system supports three types:
1. **Global Apps** (ORG-009) - First-party platform apps (foss.global, task.vc)
2. **Partner Apps** (ORG-010, DEV-008) - AppStore model for third-party apps
3. **Custom OIDC Apps** (ORG-011) - Organization-created OAuth/OIDC clients
## Related Stories
- ORG-009: Connect Global Apps
- ORG-010: Browse and Install Partner Apps
- ORG-011: Create Custom OIDC Apps
- DEV-005: Register OAuth Client App
- DEV-008: Submit App to AppStore
## Related TODOs
- `ts_idpclient/classes.idpclient.ts:30` - `id: '', // TODO`
+26 -3
View File
@@ -18,11 +18,34 @@ As a developer, I want to register my application as an OAuth client so that use
- [ ] Client credentials flow for server-to-server
## Technical Notes
- OAuth keywords in package.json suggest this is planned
- Implement OAuth 2.0 authorization server endpoints
- OAuth/OIDC client registration is now part of the Apps system
- **For organization owners**: Use Custom OIDC Apps (ORG-011) to create OAuth clients
- **For third-party developers**: Submit to AppStore (DEV-008) for public apps
- Standard OAuth 2.0 / OpenID Connect flows supported
- Scopes: openid, profile, email, organizations
- Consider OpenID Connect for identity layer
- PKCE is required for mobile and SPA security
## Implementation Path
This story's functionality is now implemented through:
1. **Custom OIDC Apps** (ORG-011) - Create org-specific OAuth clients via the Apps UI
2. **Partner Apps** (DEV-008) - Submit public apps to the AppStore
Both use the same underlying `IOAuthCredentials` model:
```typescript
interface IOAuthCredentials {
clientId: string;
clientSecretHash: string;
redirectUris: string[];
allowedScopes: string[];
grantTypes: ('authorization_code' | 'client_credentials' | 'refresh_token')[];
}
```
## Related Stories
- ORG-011: Create Custom OIDC Apps (primary implementation)
- DEV-004: Proper App ID Initialization
- DEV-008: Submit App to AppStore
## Related TODOs
- New feature - OAuth server implementation
@@ -0,0 +1,70 @@
# Submit App to AppStore
**ID:** DEV-008
**Priority:** Low
**Status:** Planned
**Phase:** 4
## User Story
As a developer, I want to submit my application to the AppStore so that other organizations can discover and install my app.
## Acceptance Criteria
- [ ] Submit a new app to the AppStore
- [ ] Provide app name, description, and logo
- [ ] Add screenshots for the store listing
- [ ] Select app category and tags
- [ ] Set pricing model (free, paid, freemium)
- [ ] Configure OAuth credentials (redirect URIs, scopes)
- [ ] Submit for review
- [ ] View submission status (draft, pending_review, approved, rejected, suspended)
- [ ] Receive notification on approval/rejection
- [ ] Edit app listing after approval
- [ ] View app analytics (install count, usage)
## Technical Notes
- Submitter organization becomes `ownerOrganizationId`
- Apps start in `draft` status, move to `pending_review` on submit
- Platform admins review and approve/reject apps
- Approved apps become visible in the AppStore
- App updates may require re-approval
## Approval Workflow
```
draft → pending_review → approved → published
↘ rejected
approved ↔ suspended (admin action)
```
## Data Model
```typescript
interface IPartnerApp {
id: string;
type: 'partner';
data: {
ownerOrganizationId: string;
appStoreMetadata: {
shortDescription: string;
longDescription: string;
screenshots: string[];
category: string;
tags: string[];
pricing: { model: 'free' | 'paid' | 'freemium' };
};
approvalStatus: 'draft' | 'pending_review' | 'approved' | 'rejected' | 'suspended';
isPublished: boolean;
installCount: number;
// ... other fields
};
}
```
## UI Components
- **AppSubmissionView** (`/account/org/:orgName/apps/submit`) - Submit new partner app form
## Related Stories
- ORG-010: Browse and Install Partner Apps
- ORG-011: Create Custom OIDC Apps
- ADM-008: Review Partner App Submissions (new admin story)
@@ -0,0 +1,65 @@
# Connect Global Apps
**ID:** ORG-009
**Priority:** High
**Status:** In Development
**Phase:** 1
## User Story
As an organization owner, I want to connect and disconnect first-party apps (foss.global, task.vc, etc.) for my organization so that my team members can use these integrated services.
## Acceptance Criteria
- [ ] View list of available global apps (foss.global, task.vc)
- [ ] See connection status for each global app
- [ ] Connect a global app to the organization
- [ ] Disconnect a global app from the organization
- [ ] View which user connected the app and when
- [ ] See what scopes/permissions each app requires
- [ ] Toggle does not require page reload
## Technical Notes
- Global apps are pre-registered by the platform administrators
- Uses `IAppConnection` to track org-to-app relationships
- Connection creates OAuth authorization for the app
- Apps access org data via granted scopes
- No credentials shown to org owners (managed by platform)
## Data Model
```typescript
interface IGlobalApp {
id: string;
type: 'global';
data: {
name: string;
description: string;
logoUrl: string;
appUrl: string;
oauthCredentials: IOAuthCredentials;
isActive: boolean;
category: string;
};
}
interface IAppConnection {
id: string;
data: {
organizationId: string;
appId: string;
appType: 'global' | 'partner' | 'custom_oidc';
status: 'active' | 'disconnected';
connectedAt: number;
connectedByUserId: string;
grantedScopes: string[];
};
}
```
## UI Components
- **AppsView** (`/account/org/:orgName/apps`) - Main tabbed interface
- **Global Apps Tab** - List of global apps with toggle switches
## Related Stories
- ORG-010: Browse and Install Partner Apps (AppStore)
- ORG-011: Create Custom OIDC Apps
- DEV-004: Proper App ID Initialization
@@ -0,0 +1,63 @@
# Browse and Install Partner Apps
**ID:** ORG-010
**Priority:** Medium
**Status:** Planned
**Phase:** 3
## User Story
As an organization owner, I want to browse and install partner apps from the AppStore so that my organization can benefit from third-party integrations.
## Acceptance Criteria
- [ ] Browse available partner apps in the AppStore
- [ ] Search apps by name or description
- [ ] Filter apps by category
- [ ] View curated sections (Featured, Popular, New)
- [ ] View app details (description, screenshots, pricing)
- [ ] See app install count and ratings
- [ ] Install/connect a partner app to the organization
- [ ] Uninstall/disconnect a partner app
- [ ] View installed apps list
## Technical Notes
- Partner apps are submitted by other organizations (DEV-008)
- Apps must be approved by platform admins before appearing in store
- Uses `IPartnerApp` with `appStoreMetadata`
- Connection uses same `IAppConnection` as global apps
## Data Model
```typescript
interface IPartnerApp {
id: string;
type: 'partner';
data: {
name: string;
description: string;
logoUrl: string;
appUrl: string;
ownerOrganizationId: string;
oauthCredentials: IOAuthCredentials;
appStoreMetadata: {
shortDescription: string;
longDescription: string;
screenshots: string[];
category: string;
tags: string[];
pricing: { model: 'free' | 'paid' | 'freemium' };
};
approvalStatus: TAppApprovalStatus;
isPublished: boolean;
installCount: number;
};
}
```
## UI Components
- **AppsView** - App Store tab with search and categories
- **AppStoreDetailView** (`/account/org/:orgName/apps/store/:appId`) - Full app details page
## Related Stories
- ORG-009: Connect Global Apps
- ORG-011: Create Custom OIDC Apps
- DEV-008: Submit App to AppStore
@@ -0,0 +1,70 @@
# Create Custom OIDC Apps
**ID:** ORG-011
**Priority:** Medium
**Status:** Planned
**Phase:** 2
## User Story
As an organization owner, I want to create custom OAuth/OIDC client applications so that I can integrate my own internal tools and services with the identity provider.
## Acceptance Criteria
- [ ] Create a new custom OIDC application
- [ ] Configure application name and description
- [ ] Upload application logo
- [ ] Set application URL
- [ ] Configure redirect URIs
- [ ] Select allowed OAuth scopes
- [ ] Choose grant types (authorization_code, client_credentials, refresh_token)
- [ ] View client ID and client secret
- [ ] Regenerate client secret if compromised
- [ ] Edit existing applications
- [ ] Delete applications
- [ ] Configure token lifetimes
## Technical Notes
- Custom OIDC apps are organization-scoped
- Client secret is hashed in database, shown only once at creation
- Redirect URIs validated to prevent open redirect attacks
- Standard OAuth 2.0 / OpenID Connect flows supported
- PKCE support for public clients
## Data Model
```typescript
interface ICustomOidcApp {
id: string;
type: 'custom_oidc';
data: {
name: string;
description: string;
logoUrl: string;
appUrl: string;
ownerOrganizationId: string;
oauthCredentials: IOAuthCredentials;
oidcSettings: {
accessTokenLifetime: number; // seconds
refreshTokenLifetime: number; // seconds
};
};
}
interface IOAuthCredentials {
clientId: string;
clientSecretHash: string;
redirectUris: string[];
allowedScopes: string[];
grantTypes: ('authorization_code' | 'client_credentials' | 'refresh_token')[];
}
```
## UI Components
- **AppsView** - Custom OIDC tab with app list
- **OidcAppFormView** (`/account/org/:orgName/apps/custom/new`) - Create new app form
- **OidcAppFormView** (`/account/org/:orgName/apps/custom/:appId`) - Edit existing app
## Related Stories
- ORG-009: Connect Global Apps
- ORG-010: Browse and Install Partner Apps
- DEV-004: Proper App ID Initialization
- DEV-005: Register OAuth Client App