@weirdfingers/baseboards 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +191 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +887 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +64 -0
  6. package/templates/README.md +120 -0
  7. package/templates/api/.env.example +62 -0
  8. package/templates/api/Dockerfile +32 -0
  9. package/templates/api/README.md +132 -0
  10. package/templates/api/alembic/env.py +106 -0
  11. package/templates/api/alembic/script.py.mako +28 -0
  12. package/templates/api/alembic/versions/20250101_000000_initial_schema.py +448 -0
  13. package/templates/api/alembic/versions/20251022_174729_remove_provider_name_from_generations.py +71 -0
  14. package/templates/api/alembic/versions/20251023_165852_switch_to_declarative_base_and_mapping.py +411 -0
  15. package/templates/api/alembic/versions/2025925_62735_add_seed_data_for_default_tenant.py +85 -0
  16. package/templates/api/alembic.ini +36 -0
  17. package/templates/api/config/generators.yaml +25 -0
  18. package/templates/api/config/storage_config.yaml +26 -0
  19. package/templates/api/docs/ADDING_GENERATORS.md +409 -0
  20. package/templates/api/docs/GENERATORS_API.md +502 -0
  21. package/templates/api/docs/MIGRATIONS.md +472 -0
  22. package/templates/api/docs/storage_providers.md +337 -0
  23. package/templates/api/pyproject.toml +165 -0
  24. package/templates/api/src/boards/__init__.py +10 -0
  25. package/templates/api/src/boards/api/app.py +171 -0
  26. package/templates/api/src/boards/api/auth.py +75 -0
  27. package/templates/api/src/boards/api/endpoints/__init__.py +3 -0
  28. package/templates/api/src/boards/api/endpoints/jobs.py +76 -0
  29. package/templates/api/src/boards/api/endpoints/setup.py +505 -0
  30. package/templates/api/src/boards/api/endpoints/sse.py +129 -0
  31. package/templates/api/src/boards/api/endpoints/storage.py +74 -0
  32. package/templates/api/src/boards/api/endpoints/tenant_registration.py +296 -0
  33. package/templates/api/src/boards/api/endpoints/webhooks.py +13 -0
  34. package/templates/api/src/boards/auth/__init__.py +15 -0
  35. package/templates/api/src/boards/auth/adapters/__init__.py +20 -0
  36. package/templates/api/src/boards/auth/adapters/auth0.py +220 -0
  37. package/templates/api/src/boards/auth/adapters/base.py +73 -0
  38. package/templates/api/src/boards/auth/adapters/clerk.py +172 -0
  39. package/templates/api/src/boards/auth/adapters/jwt.py +122 -0
  40. package/templates/api/src/boards/auth/adapters/none.py +102 -0
  41. package/templates/api/src/boards/auth/adapters/oidc.py +284 -0
  42. package/templates/api/src/boards/auth/adapters/supabase.py +110 -0
  43. package/templates/api/src/boards/auth/context.py +35 -0
  44. package/templates/api/src/boards/auth/factory.py +115 -0
  45. package/templates/api/src/boards/auth/middleware.py +221 -0
  46. package/templates/api/src/boards/auth/provisioning.py +129 -0
  47. package/templates/api/src/boards/auth/tenant_extraction.py +278 -0
  48. package/templates/api/src/boards/cli.py +354 -0
  49. package/templates/api/src/boards/config.py +116 -0
  50. package/templates/api/src/boards/database/__init__.py +7 -0
  51. package/templates/api/src/boards/database/cli.py +110 -0
  52. package/templates/api/src/boards/database/connection.py +252 -0
  53. package/templates/api/src/boards/database/models.py +19 -0
  54. package/templates/api/src/boards/database/seed_data.py +182 -0
  55. package/templates/api/src/boards/dbmodels/__init__.py +455 -0
  56. package/templates/api/src/boards/generators/__init__.py +57 -0
  57. package/templates/api/src/boards/generators/artifacts.py +53 -0
  58. package/templates/api/src/boards/generators/base.py +140 -0
  59. package/templates/api/src/boards/generators/implementations/__init__.py +12 -0
  60. package/templates/api/src/boards/generators/implementations/audio/__init__.py +3 -0
  61. package/templates/api/src/boards/generators/implementations/audio/whisper.py +66 -0
  62. package/templates/api/src/boards/generators/implementations/image/__init__.py +3 -0
  63. package/templates/api/src/boards/generators/implementations/image/dalle3.py +93 -0
  64. package/templates/api/src/boards/generators/implementations/image/flux_pro.py +85 -0
  65. package/templates/api/src/boards/generators/implementations/video/__init__.py +3 -0
  66. package/templates/api/src/boards/generators/implementations/video/lipsync.py +70 -0
  67. package/templates/api/src/boards/generators/loader.py +253 -0
  68. package/templates/api/src/boards/generators/registry.py +114 -0
  69. package/templates/api/src/boards/generators/resolution.py +515 -0
  70. package/templates/api/src/boards/generators/testmods/class_gen.py +34 -0
  71. package/templates/api/src/boards/generators/testmods/import_side_effect.py +35 -0
  72. package/templates/api/src/boards/graphql/__init__.py +7 -0
  73. package/templates/api/src/boards/graphql/access_control.py +136 -0
  74. package/templates/api/src/boards/graphql/mutations/root.py +136 -0
  75. package/templates/api/src/boards/graphql/queries/root.py +116 -0
  76. package/templates/api/src/boards/graphql/resolvers/__init__.py +8 -0
  77. package/templates/api/src/boards/graphql/resolvers/auth.py +12 -0
  78. package/templates/api/src/boards/graphql/resolvers/board.py +1055 -0
  79. package/templates/api/src/boards/graphql/resolvers/generation.py +889 -0
  80. package/templates/api/src/boards/graphql/resolvers/generator.py +50 -0
  81. package/templates/api/src/boards/graphql/resolvers/user.py +25 -0
  82. package/templates/api/src/boards/graphql/schema.py +81 -0
  83. package/templates/api/src/boards/graphql/types/board.py +102 -0
  84. package/templates/api/src/boards/graphql/types/generation.py +130 -0
  85. package/templates/api/src/boards/graphql/types/generator.py +17 -0
  86. package/templates/api/src/boards/graphql/types/user.py +47 -0
  87. package/templates/api/src/boards/jobs/repository.py +104 -0
  88. package/templates/api/src/boards/logging.py +195 -0
  89. package/templates/api/src/boards/middleware.py +339 -0
  90. package/templates/api/src/boards/progress/__init__.py +4 -0
  91. package/templates/api/src/boards/progress/models.py +25 -0
  92. package/templates/api/src/boards/progress/publisher.py +64 -0
  93. package/templates/api/src/boards/py.typed +0 -0
  94. package/templates/api/src/boards/redis_pool.py +118 -0
  95. package/templates/api/src/boards/storage/__init__.py +52 -0
  96. package/templates/api/src/boards/storage/base.py +363 -0
  97. package/templates/api/src/boards/storage/config.py +187 -0
  98. package/templates/api/src/boards/storage/factory.py +278 -0
  99. package/templates/api/src/boards/storage/implementations/__init__.py +27 -0
  100. package/templates/api/src/boards/storage/implementations/gcs.py +340 -0
  101. package/templates/api/src/boards/storage/implementations/local.py +201 -0
  102. package/templates/api/src/boards/storage/implementations/s3.py +294 -0
  103. package/templates/api/src/boards/storage/implementations/supabase.py +218 -0
  104. package/templates/api/src/boards/tenant_isolation.py +446 -0
  105. package/templates/api/src/boards/validation.py +262 -0
  106. package/templates/api/src/boards/workers/__init__.py +1 -0
  107. package/templates/api/src/boards/workers/actors.py +201 -0
  108. package/templates/api/src/boards/workers/cli.py +125 -0
  109. package/templates/api/src/boards/workers/context.py +188 -0
  110. package/templates/api/src/boards/workers/middleware.py +58 -0
  111. package/templates/api/src/py.typed +0 -0
  112. package/templates/compose.dev.yaml +39 -0
  113. package/templates/compose.yaml +109 -0
  114. package/templates/docker/env.example +23 -0
  115. package/templates/web/.env.example +28 -0
  116. package/templates/web/Dockerfile +51 -0
  117. package/templates/web/components.json +22 -0
  118. package/templates/web/imageLoader.js +18 -0
  119. package/templates/web/next-env.d.ts +5 -0
  120. package/templates/web/next.config.js +36 -0
  121. package/templates/web/package.json +37 -0
  122. package/templates/web/postcss.config.mjs +7 -0
  123. package/templates/web/public/favicon.ico +0 -0
  124. package/templates/web/src/app/boards/[boardId]/page.tsx +232 -0
  125. package/templates/web/src/app/globals.css +120 -0
  126. package/templates/web/src/app/layout.tsx +21 -0
  127. package/templates/web/src/app/page.tsx +35 -0
  128. package/templates/web/src/app/providers.tsx +18 -0
  129. package/templates/web/src/components/boards/ArtifactInputSlots.tsx +142 -0
  130. package/templates/web/src/components/boards/ArtifactPreview.tsx +125 -0
  131. package/templates/web/src/components/boards/GenerationGrid.tsx +45 -0
  132. package/templates/web/src/components/boards/GenerationInput.tsx +251 -0
  133. package/templates/web/src/components/boards/GeneratorSelector.tsx +89 -0
  134. package/templates/web/src/components/header.tsx +30 -0
  135. package/templates/web/src/components/ui/button.tsx +58 -0
  136. package/templates/web/src/components/ui/card.tsx +92 -0
  137. package/templates/web/src/components/ui/navigation-menu.tsx +168 -0
  138. package/templates/web/src/lib/utils.ts +6 -0
  139. package/templates/web/tsconfig.json +47 -0
@@ -0,0 +1,337 @@
1
+ # Storage Providers
2
+
3
+ Boards supports multiple storage providers for artifact storage through a pluggable architecture. This document describes the available providers and their configuration options.
4
+
5
+ ## Available Providers
6
+
7
+ ### Local Storage
8
+
9
+ The local filesystem provider is ideal for development and testing.
10
+
11
+ **Features:**
12
+
13
+ - Stores files on the local filesystem
14
+ - Optional public URL serving for development
15
+ - No external dependencies
16
+ - Fast for small to medium files
17
+
18
+ **Configuration:**
19
+
20
+ ```yaml
21
+ providers:
22
+ local:
23
+ type: "local"
24
+ config:
25
+ base_path: "/tmp/boards/storage" # Storage directory
26
+ public_url_base: "http://localhost:8088/api/storage" # Optional: base URL for serving files
27
+ ```
28
+
29
+ **Use Cases:**
30
+
31
+ - Local development
32
+ - Testing environments
33
+ - Small deployments without cloud requirements
34
+
35
+ ---
36
+
37
+ ### AWS S3
38
+
39
+ The S3 provider offers robust cloud storage with optional CloudFront CDN integration.
40
+
41
+ **Features:**
42
+
43
+ - Scalable cloud storage
44
+ - Server-side encryption
45
+ - CloudFront CDN integration
46
+ - Presigned URLs for direct client uploads
47
+ - Multiple storage classes for cost optimization
48
+ - Cross-region replication support
49
+
50
+ **Dependencies:**
51
+
52
+ ```bash
53
+ pip install boto3 aioboto3
54
+ # or
55
+ pip install boards-backend[storage-s3]
56
+ ```
57
+
58
+ **Configuration:**
59
+
60
+ ```yaml
61
+ providers:
62
+ s3:
63
+ type: "s3"
64
+ config:
65
+ bucket: "my-boards-bucket" # Required: S3 bucket name
66
+ region: "us-east-1" # AWS region
67
+ aws_access_key_id: "${AWS_ACCESS_KEY_ID}" # AWS credentials
68
+ aws_secret_access_key: "${AWS_SECRET_ACCESS_KEY}"
69
+ aws_session_token: "${AWS_SESSION_TOKEN}" # Optional: for temporary credentials
70
+ endpoint_url: "https://s3.amazonaws.com" # Optional: custom endpoint (for S3-compatible services)
71
+ cloudfront_domain: "d123.cloudfront.net" # Optional: CloudFront distribution
72
+ upload_config: # Optional: S3 upload parameters
73
+ ServerSideEncryption: "AES256"
74
+ StorageClass: "STANDARD"
75
+ # Or use KMS encryption:
76
+ # ServerSideEncryption: "aws:kms"
77
+ # SSEKMSKeyId: "arn:aws:kms:region:account:key/key-id"
78
+ ```
79
+
80
+ **Environment Variables:**
81
+
82
+ - `AWS_ACCESS_KEY_ID`: AWS access key (if not in config)
83
+ - `AWS_SECRET_ACCESS_KEY`: AWS secret key (if not in config)
84
+ - `AWS_SESSION_TOKEN`: Temporary session token (optional)
85
+ - `AWS_REGION`: Default region (if not in config)
86
+
87
+ **Use Cases:**
88
+
89
+ - Production deployments
90
+ - Large file storage
91
+ - Global content distribution with CloudFront
92
+ - Compliance requirements (encryption, audit trails)
93
+ - Integration with other AWS services
94
+
95
+ ---
96
+
97
+ ### Google Cloud Storage (GCS)
98
+
99
+ The GCS provider integrates with Google Cloud Platform and Cloud CDN.
100
+
101
+ **Features:**
102
+
103
+ - Google Cloud native storage
104
+ - Automatic encryption at rest
105
+ - Cloud CDN integration
106
+ - Multi-regional storage options
107
+ - IAM integration with fine-grained permissions
108
+ - Lifecycle management policies
109
+
110
+ **Dependencies:**
111
+
112
+ ```bash
113
+ pip install google-cloud-storage
114
+ # or
115
+ pip install boards-backend[storage-gcs]
116
+ ```
117
+
118
+ **Configuration:**
119
+
120
+ ```yaml
121
+ providers:
122
+ gcs:
123
+ type: "gcs"
124
+ config:
125
+ bucket: "my-boards-gcs-bucket" # Required: GCS bucket name
126
+ project_id: "my-gcp-project" # GCP project ID
127
+ # Authentication options (choose one):
128
+ credentials_path: "/path/to/service-account-key.json" # Service account key file
129
+ credentials_json: "${GCP_SERVICE_ACCOUNT_JSON}" # Service account JSON as string
130
+ # Or use default credentials (gcloud, environment, etc.)
131
+ cdn_domain: "cdn.example.com" # Optional: Cloud CDN domain
132
+ upload_config: # Optional: GCS upload parameters
133
+ cache_control: "public, max-age=3600"
134
+ predefined_acl: "bucket-owner-read"
135
+ ```
136
+
137
+ **Authentication Methods:**
138
+
139
+ 1. **Service Account Key File:**
140
+
141
+ ```yaml
142
+ credentials_path: "/path/to/service-account-key.json"
143
+ ```
144
+
145
+ 2. **Service Account JSON String:**
146
+
147
+ ```yaml
148
+ credentials_json: "${GCP_SERVICE_ACCOUNT_JSON}"
149
+ ```
150
+
151
+ 3. **Default Credentials (recommended for production):**
152
+ - Google Cloud SDK (`gcloud auth application-default login`)
153
+ - Environment variable `GOOGLE_APPLICATION_CREDENTIALS`
154
+ - Compute Engine/GKE service accounts
155
+ - Cloud Run/Cloud Functions default credentials
156
+
157
+ **Use Cases:**
158
+
159
+ - Google Cloud Platform deployments
160
+ - Integration with other GCP services
161
+ - Global content distribution
162
+ - Machine learning workflows (easy integration with AI Platform)
163
+ - Multi-regional applications
164
+
165
+ ---
166
+
167
+ ### Supabase Storage
168
+
169
+ The Supabase provider integrates with Supabase's storage and authentication system.
170
+
171
+ **Features:**
172
+
173
+ - Integrated with Supabase auth
174
+ - Built-in CDN
175
+ - Row Level Security (RLS) integration
176
+ - Real-time subscriptions
177
+ - Automatic image transformations
178
+
179
+ **Dependencies:**
180
+
181
+ ```bash
182
+ pip install supabase
183
+ ```
184
+
185
+ **Configuration:**
186
+
187
+ ```yaml
188
+ providers:
189
+ supabase:
190
+ type: "supabase"
191
+ config:
192
+ url: "${SUPABASE_URL}" # Supabase project URL
193
+ key: "${SUPABASE_ANON_KEY}" # Supabase anon key
194
+ bucket: "boards-artifacts" # Storage bucket name
195
+ ```
196
+
197
+ **Use Cases:**
198
+
199
+ - Supabase-based applications
200
+ - Real-time collaborative features
201
+ - Integrated authentication and storage
202
+ - Rapid prototyping
203
+
204
+ ## Provider Selection and Routing
205
+
206
+ Boards supports intelligent provider selection through routing rules:
207
+
208
+ ```yaml
209
+ routing_rules:
210
+ # Large files go to S3
211
+ - condition:
212
+ size_gt: "50MB"
213
+ provider: "s3"
214
+
215
+ # Images go to GCS with CDN
216
+ - condition:
217
+ artifact_type: "image"
218
+ provider: "gcs"
219
+
220
+ # Videos go to S3 for CloudFront streaming
221
+ - condition:
222
+ artifact_type: "video"
223
+ provider: "s3"
224
+
225
+ # Default fallback
226
+ - provider: "local"
227
+ ```
228
+
229
+ ## Best Practices
230
+
231
+ ### Security
232
+
233
+ 1. **Never hardcode credentials** in configuration files
234
+ 2. **Use environment variables** or secure credential management
235
+ 3. **Enable encryption at rest** for sensitive data
236
+ 4. **Use IAM roles** instead of access keys when possible
237
+ 5. **Implement bucket policies** for additional security
238
+
239
+ ### Performance
240
+
241
+ 1. **Choose regions close to your users** for better latency
242
+ 2. **Use CDN/CloudFront** for frequently accessed content
243
+ 3. **Consider storage classes** for cost optimization
244
+ 4. **Implement caching** at the application level
245
+ 5. **Use presigned URLs** for direct client uploads
246
+
247
+ ### Cost Optimization
248
+
249
+ 1. **Use appropriate storage classes** (Standard, IA, Glacier, etc.)
250
+ 2. **Implement lifecycle policies** for automatic data management
251
+ 3. **Monitor usage and costs** regularly
252
+ 4. **Use compression** for text-based content
253
+ 5. **Clean up unused files** periodically
254
+
255
+ ### Development vs Production
256
+
257
+ **Development:**
258
+
259
+ ```yaml
260
+ default_provider: "local"
261
+ providers:
262
+ local:
263
+ type: "local"
264
+ config:
265
+ base_path: "/tmp/boards/storage"
266
+ ```
267
+
268
+ **Production:**
269
+
270
+ ```yaml
271
+ default_provider: "s3"
272
+ providers:
273
+ s3:
274
+ type: "s3"
275
+ config:
276
+ bucket: "prod-boards-artifacts"
277
+ cloudfront_domain: "cdn.example.com"
278
+ gcs:
279
+ type: "gcs"
280
+ config:
281
+ bucket: "prod-boards-media"
282
+ cdn_domain: "media.example.com"
283
+ ```
284
+
285
+ ## Migration Between Providers
286
+
287
+ When migrating between providers, consider:
288
+
289
+ 1. **Gradual migration** using routing rules
290
+ 2. **Data consistency** during the migration
291
+ 3. **URL updates** for existing references
292
+ 4. **Testing** with non-critical data first
293
+ 5. **Backup strategies** for data safety
294
+
295
+ Example gradual migration:
296
+
297
+ ```yaml
298
+ # Phase 1: Route new uploads to S3, keep existing on local
299
+ routing_rules:
300
+ - condition:
301
+ artifact_type: "image"
302
+ provider: "s3"
303
+ - provider: "local" # Existing files
304
+
305
+ # Phase 2: Migrate all new uploads to S3
306
+ routing_rules:
307
+ - provider: "s3"
308
+ ```
309
+
310
+ ## Troubleshooting
311
+
312
+ ### Common Issues
313
+
314
+ 1. **Authentication errors**: Check credentials and permissions
315
+ 2. **Bucket access denied**: Verify bucket policies and IAM permissions
316
+ 3. **Network timeouts**: Check network connectivity and endpoint URLs
317
+ 4. **Large file uploads**: Consider chunked uploads and timeout settings
318
+ 5. **CDN cache issues**: Check cache headers and purge policies
319
+
320
+ ### Debugging
321
+
322
+ Enable debug logging:
323
+
324
+ ```python
325
+ import logging
326
+ logging.getLogger("boards.storage").setLevel(logging.DEBUG)
327
+ ```
328
+
329
+ ### Monitoring
330
+
331
+ Key metrics to monitor:
332
+
333
+ - Upload success rates
334
+ - Download latency
335
+ - Storage costs
336
+ - Error rates by provider
337
+ - CDN hit rates (if applicable)
@@ -0,0 +1,165 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "weirdfingers-boards"
7
+ dynamic = ["version"]
8
+ description = "Backend API server for Boards - AI creative toolkit with GraphQL, auth adapters, and generation workers"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Boards Contributors", email = "ai.overlord@weirdfingers.com" },
14
+ ]
15
+ keywords = [
16
+ "ai",
17
+ "creative",
18
+ "toolkit",
19
+ "graphql",
20
+ "fastapi",
21
+ "strawberry",
22
+ "auth",
23
+ "generation",
24
+ ]
25
+ classifiers = [
26
+ "Development Status :: 3 - Alpha",
27
+ "Intended Audience :: Developers",
28
+ "License :: OSI Approved :: MIT License",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
32
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
33
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
34
+ "Framework :: FastAPI",
35
+ "Framework :: AsyncIO",
36
+ ]
37
+ dependencies = [
38
+ "sqlalchemy>=2.0.0",
39
+ "supabase>=2.0.0",
40
+ "pydantic>=2.0.0",
41
+ "pydantic-settings>=2.0.0",
42
+ "httpx>=0.24.0",
43
+ "python-dotenv>=1.0.0",
44
+ "strawberry-graphql[fastapi]>=0.200.0",
45
+ "fastapi>=0.100.0",
46
+ "uvicorn[standard]>=0.23.0",
47
+ "dramatiq[redis,watch]>=1.15.0",
48
+ "pillow>=10.0.0",
49
+ "numpy>=1.24.0",
50
+ "psycopg2-binary>=2.9.0",
51
+ "structlog>=23.0.0",
52
+ "asyncpg>=0.29.0",
53
+ "alembic>=1.13.2",
54
+ "aiofiles>=23.0.0",
55
+ "pyyaml>=6.0.0",
56
+ "click>=8.0.0",
57
+ "redis>=5.0.0",
58
+ "pyjwt[crypto]>=2.8.0",
59
+ "psutil>=7.0.0",
60
+ ]
61
+
62
+ [project.optional-dependencies]
63
+ dev = [
64
+ "pytest>=7.0.0",
65
+ "pytest-asyncio>=0.21.0",
66
+ "pytest-postgresql>=6.0.0",
67
+ "pytest-cov>=4.0.0",
68
+ "ruff>=0.1.0",
69
+ "pyright>=1.1.0",
70
+ "black>=23.0.0",
71
+ "pre-commit>=3.0.0",
72
+ # Include all provider deps for typecheck
73
+ "openai>=1.60.1",
74
+ "anthropic>=0.25.0",
75
+ "replicate>=1.0.4",
76
+ "together>=1.0.0",
77
+ # Include all storage deps for typecheck
78
+ "boto3>=1.34.0",
79
+ "aioboto3>=12.0.0",
80
+ "google-cloud-storage>=2.10.0",
81
+ # Type stubs
82
+ "types-redis>=4.6.0",
83
+ ]
84
+ providers = [
85
+ "openai>=1.60.1",
86
+ "anthropic>=0.25.0",
87
+ "replicate>=1.0.4",
88
+ "together>=1.0.0",
89
+ ]
90
+ storage-s3 = ["boto3>=1.34.0", "aioboto3>=12.0.0"]
91
+ storage-gcs = ["google-cloud-storage>=2.10.0"]
92
+
93
+ [project.urls]
94
+ Homepage = "https://github.com/weirdfingers/boards"
95
+ Documentation = "https://docs.boards.io"
96
+ Repository = "https://github.com/weirdfingers/boards"
97
+ Issues = "https://github.com/weirdfingers/boards/issues"
98
+ Changelog = "https://github.com/weirdfingers/boards/blob/main/CHANGELOG.md"
99
+
100
+ [project.scripts]
101
+ boards-server = "boards.cli:main"
102
+ boards-worker = "boards.workers.cli:main"
103
+ boards-migrate = "boards.database.cli:main"
104
+
105
+ [tool.setuptools.packages.find]
106
+ where = ["src"]
107
+
108
+ [tool.ruff]
109
+ line-length = 100
110
+ target-version = "py312"
111
+ exclude = ["alembic"]
112
+
113
+ [tool.ruff.lint]
114
+ select = [
115
+ "E", # pycodestyle errors
116
+ "W", # pycodestyle warnings
117
+ "F", # pyflakes
118
+ "I", # isort
119
+ "B", # flake8-bugbear
120
+ "C4", # flake8-comprehensions
121
+ "UP", # pyupgrade
122
+ ]
123
+
124
+ [tool.ruff.lint.per-file-ignores]
125
+ # FastAPI uses Depends in function signatures
126
+ "src/boards/api/**/*.py" = ["B008"]
127
+ "tests/**/test_*.py" = ["B008"]
128
+ # Alembic needs imports after path manipulation
129
+ "alembic/env.py" = ["E402"]
130
+ # __init__.py files often have unused imports for re-export
131
+ "**/__init__.py" = ["F401"]
132
+
133
+ [tool.pytest.ini_options]
134
+ testpaths = ["tests"]
135
+ pythonpath = ["src"]
136
+ asyncio_mode = "auto"
137
+
138
+ [tool.setuptools.dynamic]
139
+ version = { attr = "boards.__version__" }
140
+
141
+ [tool.uv]
142
+ dev-dependencies = [
143
+ "pytest>=7.0.0",
144
+ "pytest-asyncio>=0.21.0",
145
+ "pytest-postgresql>=6.0.0",
146
+ "pytest-cov>=4.0.0",
147
+ "ruff>=0.1.0",
148
+ "pyright>=1.1.0",
149
+ "black>=23.0.0",
150
+ "pre-commit>=3.0.0",
151
+ "build>=1.3.0",
152
+ "twine>=6.1.0",
153
+ "watchfiles>=1.1.0",
154
+ # Include all provider deps for typecheck
155
+ "openai>=1.60.1",
156
+ "anthropic>=0.25.0",
157
+ "replicate>=1.0.4",
158
+ "together>=1.0.0",
159
+ # Include all storage deps for typecheck
160
+ "boto3>=1.34.0",
161
+ "aioboto3>=12.0.0",
162
+ "google-cloud-storage>=2.10.0",
163
+ # Type stubs
164
+ "types-redis>=4.6.0",
165
+ ]
@@ -0,0 +1,10 @@
1
+ """
2
+ Boards Backend SDK
3
+ Open-source creative toolkit for AI-generated content
4
+ """
5
+
6
+ __version__ = "0.2.0"
7
+
8
+ from .config import settings
9
+
10
+ __all__ = ["settings", "__version__"]
@@ -0,0 +1,171 @@
1
+ """
2
+ Main FastAPI application for Boards backend
3
+ """
4
+
5
+ import os
6
+ from contextlib import asynccontextmanager
7
+
8
+ from fastapi import FastAPI
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+
11
+ from ..config import initialize_generator_api_keys, settings
12
+ from ..database import init_database
13
+ from ..generators.loader import load_generators_from_config
14
+ from ..logging import configure_logging, get_logger
15
+ from ..middleware import LoggingContextMiddleware, TenantRoutingMiddleware
16
+
17
+ # Configure logging before creating logger
18
+ configure_logging(debug=settings.debug)
19
+ logger = get_logger(__name__)
20
+
21
+
22
+ @asynccontextmanager
23
+ async def lifespan(app: FastAPI):
24
+ """Application lifespan manager."""
25
+ # Startup
26
+ logger.info("Starting Boards API...")
27
+ init_database()
28
+ logger.info("Database initialized")
29
+
30
+ # Initialize generator API keys from settings
31
+ initialize_generator_api_keys()
32
+ logger.info("Generator API keys initialized")
33
+
34
+ # Load generators based on configuration
35
+ try:
36
+ load_generators_from_config()
37
+ logger.info(
38
+ "Generators configured and registered",
39
+ names=list(
40
+ __import__(
41
+ "boards.generators.registry", fromlist=["registry"]
42
+ ).registry.list_names()
43
+ ),
44
+ )
45
+ except Exception as e:
46
+ # Fail fast: strict mode default may raise here
47
+ logger.error("Failed to configure generators", error=str(e))
48
+ raise
49
+
50
+ # Run comprehensive startup validation
51
+ try:
52
+ from ..validation import (
53
+ ValidationError,
54
+ get_startup_recommendations,
55
+ validate_startup_configuration,
56
+ )
57
+
58
+ validation_results = await validate_startup_configuration()
59
+
60
+ if not validation_results["overall_valid"]:
61
+ # Log detailed error information
62
+ logger.error(
63
+ "Application configuration validation failed - some features may not work properly",
64
+ database_errors=validation_results.get("database", {}).get("errors", []),
65
+ tenant_errors=validation_results["tenant"].get("errors", []),
66
+ auth_errors=validation_results["auth"].get("errors", []),
67
+ )
68
+
69
+ # In production, we might want to fail hard here
70
+ if settings.environment.lower() in ("production", "prod"):
71
+ raise ValidationError("Critical configuration validation failed in production")
72
+
73
+ # Log recommendations
74
+ recommendations = get_startup_recommendations(validation_results)
75
+ if recommendations:
76
+ logger.info("Configuration recommendations", recommendations=recommendations)
77
+
78
+ except ValidationError:
79
+ # Re-raise validation errors to fail startup
80
+ raise
81
+ except Exception as e:
82
+ logger.error(
83
+ "Unexpected error during startup validation",
84
+ error=str(e),
85
+ note="Application will continue but may have configuration issues",
86
+ )
87
+
88
+ yield
89
+
90
+ # Shutdown
91
+ logger.info("Shutting down Boards API...")
92
+
93
+
94
+ def create_app() -> FastAPI:
95
+ """Create and configure the FastAPI application."""
96
+
97
+ app = FastAPI(
98
+ title="Boards API",
99
+ description="Open-source creative toolkit for AI-generated content",
100
+ version="0.1.0",
101
+ lifespan=lifespan,
102
+ debug=settings.debug,
103
+ )
104
+
105
+ # Add tenant routing middleware first (runs before logging)
106
+ app.add_middleware(TenantRoutingMiddleware)
107
+
108
+ # Add logging context middleware
109
+ app.add_middleware(LoggingContextMiddleware)
110
+
111
+ # CORS configuration
112
+ app.add_middleware(
113
+ CORSMiddleware,
114
+ allow_origins=settings.cors_origins,
115
+ allow_credentials=True,
116
+ allow_methods=["*"],
117
+ allow_headers=["*"],
118
+ )
119
+
120
+ # Health check endpoint
121
+ @app.get("/health")
122
+ async def health_check(): # pyright: ignore [reportUnusedFunction]
123
+ """Health check endpoint."""
124
+ return {"status": "healthy", "version": "0.1.0"}
125
+
126
+ # GraphQL endpoint (allow disabling for tests)
127
+ if not os.getenv("BOARDS_DISABLE_GRAPHQL"):
128
+ try:
129
+ from ..graphql.schema import create_graphql_router, validate_schema
130
+
131
+ # Validate schema at startup to catch circular reference errors early
132
+ logger.info("Validating GraphQL schema...")
133
+ validate_schema()
134
+
135
+ # Create and mount the GraphQL router
136
+ graphql_router = create_graphql_router()
137
+ app.include_router(graphql_router, prefix="")
138
+ logger.info("GraphQL endpoint initialized successfully", endpoint="/graphql")
139
+ except Exception as e: # pragma: no cover
140
+ logger.error("Failed to initialize GraphQL endpoint", error=str(e))
141
+ # Re-raise to fail fast - server should not start with broken GraphQL
142
+ raise
143
+
144
+ # REST API endpoints (for SSE, webhooks, etc.)
145
+ from .endpoints import jobs, setup, sse, storage, tenant_registration, webhooks
146
+
147
+ app.include_router(sse.router, prefix="/api/sse", tags=["SSE"])
148
+ app.include_router(jobs.router, prefix="/api/jobs", tags=["Jobs"])
149
+ app.include_router(webhooks.router, prefix="/api/webhooks", tags=["Webhooks"])
150
+ app.include_router(storage.router, prefix="/api/storage", tags=["Storage"])
151
+ app.include_router(setup.router, prefix="/api/setup", tags=["Setup"])
152
+ app.include_router(
153
+ tenant_registration.router, prefix="/api/tenants", tags=["Tenant Registration"]
154
+ )
155
+
156
+ return app
157
+
158
+
159
+ # Create the main application instance
160
+ app = create_app()
161
+
162
+ if __name__ == "__main__":
163
+ import uvicorn
164
+
165
+ uvicorn.run(
166
+ "boards.api.app:app",
167
+ host=settings.api_host,
168
+ port=settings.api_port,
169
+ reload=settings.api_reload,
170
+ log_level=settings.log_level.lower(),
171
+ )