adapt-server 0.1.0__tar.gz

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 (96) hide show
  1. adapt_server-0.1.0/LICENSE +21 -0
  2. adapt_server-0.1.0/PKG-INFO +576 -0
  3. adapt_server-0.1.0/README.md +534 -0
  4. adapt_server-0.1.0/adapt/__init__.py +3 -0
  5. adapt_server-0.1.0/adapt/__main__.py +5 -0
  6. adapt_server-0.1.0/adapt/admin/__init__.py +10 -0
  7. adapt_server-0.1.0/adapt/admin/api_keys.py +123 -0
  8. adapt_server-0.1.0/adapt/admin/audit_logs.py +66 -0
  9. adapt_server-0.1.0/adapt/admin/cache.py +78 -0
  10. adapt_server-0.1.0/adapt/admin/groups.py +170 -0
  11. adapt_server-0.1.0/adapt/admin/locks.py +82 -0
  12. adapt_server-0.1.0/adapt/admin/models.py +37 -0
  13. adapt_server-0.1.0/adapt/admin/permissions.py +169 -0
  14. adapt_server-0.1.0/adapt/admin/resources.py +25 -0
  15. adapt_server-0.1.0/adapt/admin/ui.py +32 -0
  16. adapt_server-0.1.0/adapt/admin/users.py +114 -0
  17. adapt_server-0.1.0/adapt/api_keys.py +82 -0
  18. adapt_server-0.1.0/adapt/app.py +256 -0
  19. adapt_server-0.1.0/adapt/audit.py +49 -0
  20. adapt_server-0.1.0/adapt/auth/__init__.py +15 -0
  21. adapt_server-0.1.0/adapt/auth/dependencies.py +109 -0
  22. adapt_server-0.1.0/adapt/auth/password.py +24 -0
  23. adapt_server-0.1.0/adapt/auth/routes.py +198 -0
  24. adapt_server-0.1.0/adapt/auth/session.py +53 -0
  25. adapt_server-0.1.0/adapt/cache.py +152 -0
  26. adapt_server-0.1.0/adapt/cli.py +124 -0
  27. adapt_server-0.1.0/adapt/commands/__init__.py +1 -0
  28. adapt_server-0.1.0/adapt/commands/addsuperuser.py +46 -0
  29. adapt_server-0.1.0/adapt/commands/admin/__init__.py +73 -0
  30. adapt_server-0.1.0/adapt/commands/admin/add_to_group.py +42 -0
  31. adapt_server-0.1.0/adapt/commands/admin/create_group.py +29 -0
  32. adapt_server-0.1.0/adapt/commands/admin/create_permissions.py +167 -0
  33. adapt_server-0.1.0/adapt/commands/admin/create_user.py +40 -0
  34. adapt_server-0.1.0/adapt/commands/admin/delete_group.py +28 -0
  35. adapt_server-0.1.0/adapt/commands/admin/delete_user.py +28 -0
  36. adapt_server-0.1.0/adapt/commands/admin/list_groups.py +57 -0
  37. adapt_server-0.1.0/adapt/commands/admin/list_resources.py +20 -0
  38. adapt_server-0.1.0/adapt/commands/admin/list_users.py +32 -0
  39. adapt_server-0.1.0/adapt/commands/admin/remove_from_group.py +42 -0
  40. adapt_server-0.1.0/adapt/commands/check.py +41 -0
  41. adapt_server-0.1.0/adapt/commands/list_endpoints.py +37 -0
  42. adapt_server-0.1.0/adapt/commands/serve.py +78 -0
  43. adapt_server-0.1.0/adapt/config.py +230 -0
  44. adapt_server-0.1.0/adapt/discovery.py +117 -0
  45. adapt_server-0.1.0/adapt/locks.py +140 -0
  46. adapt_server-0.1.0/adapt/models.py +15 -0
  47. adapt_server-0.1.0/adapt/permissions.py +57 -0
  48. adapt_server-0.1.0/adapt/plugins/__init__.py +22 -0
  49. adapt_server-0.1.0/adapt/plugins/base.py +137 -0
  50. adapt_server-0.1.0/adapt/plugins/csv_plugin.py +67 -0
  51. adapt_server-0.1.0/adapt/plugins/dataset_plugin.py +390 -0
  52. adapt_server-0.1.0/adapt/plugins/excel_plugin.py +130 -0
  53. adapt_server-0.1.0/adapt/plugins/html_plugin.py +104 -0
  54. adapt_server-0.1.0/adapt/plugins/markdown_plugin.py +113 -0
  55. adapt_server-0.1.0/adapt/plugins/media_plugin.py +202 -0
  56. adapt_server-0.1.0/adapt/plugins/parquet_plugin.py +156 -0
  57. adapt_server-0.1.0/adapt/plugins/python_plugin.py +92 -0
  58. adapt_server-0.1.0/adapt/routes.py +68 -0
  59. adapt_server-0.1.0/adapt/static/admin/app.js +672 -0
  60. adapt_server-0.1.0/adapt/static/admin/style.css +299 -0
  61. adapt_server-0.1.0/adapt/storage.py +138 -0
  62. adapt_server-0.1.0/adapt/templates/admin/index.html +452 -0
  63. adapt_server-0.1.0/adapt/templates/admin_base.html +78 -0
  64. adapt_server-0.1.0/adapt/templates/base.html +81 -0
  65. adapt_server-0.1.0/adapt/templates/datatable.html +234 -0
  66. adapt_server-0.1.0/adapt/templates/landing.html +56 -0
  67. adapt_server-0.1.0/adapt/templates/login.html +128 -0
  68. adapt_server-0.1.0/adapt/templates/media_gallery.html +51 -0
  69. adapt_server-0.1.0/adapt/templates/media_player.html +23 -0
  70. adapt_server-0.1.0/adapt/templates/profile.html +169 -0
  71. adapt_server-0.1.0/adapt/utils/__init__.py +82 -0
  72. adapt_server-0.1.0/adapt/utils/query.py +91 -0
  73. adapt_server-0.1.0/adapt_server.egg-info/PKG-INFO +576 -0
  74. adapt_server-0.1.0/adapt_server.egg-info/SOURCES.txt +94 -0
  75. adapt_server-0.1.0/adapt_server.egg-info/dependency_links.txt +1 -0
  76. adapt_server-0.1.0/adapt_server.egg-info/entry_points.txt +2 -0
  77. adapt_server-0.1.0/adapt_server.egg-info/requires.txt +19 -0
  78. adapt_server-0.1.0/adapt_server.egg-info/top_level.txt +1 -0
  79. adapt_server-0.1.0/pyproject.toml +66 -0
  80. adapt_server-0.1.0/setup.cfg +4 -0
  81. adapt_server-0.1.0/tests/test_admin.py +488 -0
  82. adapt_server-0.1.0/tests/test_auth.py +342 -0
  83. adapt_server-0.1.0/tests/test_config.py +186 -0
  84. adapt_server-0.1.0/tests/test_constraints.py +57 -0
  85. adapt_server-0.1.0/tests/test_csv_plugin.py +284 -0
  86. adapt_server-0.1.0/tests/test_dataset_plugin.py +127 -0
  87. adapt_server-0.1.0/tests/test_discovery.py +79 -0
  88. adapt_server-0.1.0/tests/test_html_plugin.py +72 -0
  89. adapt_server-0.1.0/tests/test_integration.py +270 -0
  90. adapt_server-0.1.0/tests/test_locks.py +165 -0
  91. adapt_server-0.1.0/tests/test_markdown_plugin.py +72 -0
  92. adapt_server-0.1.0/tests/test_on_delete.py +95 -0
  93. adapt_server-0.1.0/tests/test_parquet_plugin.py +50 -0
  94. adapt_server-0.1.0/tests/test_phase3.py +140 -0
  95. adapt_server-0.1.0/tests/test_plugin_interface.py +69 -0
  96. adapt_server-0.1.0/tests/test_readonly.py +70 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 notesofcliff
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,576 @@
1
+ Metadata-Version: 2.4
2
+ Name: adapt-server
3
+ Version: 0.1.0
4
+ Summary: Adaptive file-backed FastAPI server that turns datasets into CRUD APIs and UIs.
5
+ Author-email: notesofcliff <notesofcliff@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/notesofcliff/adapt
8
+ Project-URL: Repository, https://github.com/notesofcliff/adapt
9
+ Project-URL: Issues, https://github.com/notesofcliff/adapt/issues
10
+ Keywords: fastapi,api,csv,excel,parquet,markdown,media
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Framework :: FastAPI
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: fastapi
24
+ Requires-Dist: uvicorn
25
+ Requires-Dist: sqlmodel
26
+ Requires-Dist: pendulum
27
+ Requires-Dist: watchfiles
28
+ Requires-Dist: jinja2
29
+ Requires-Dist: openpyxl
30
+ Requires-Dist: markdown
31
+ Requires-Dist: python-multipart
32
+ Requires-Dist: mutagen
33
+ Requires-Dist: moviepy
34
+ Requires-Dist: pillow
35
+ Requires-Dist: python-json-logger
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest; extra == "dev"
38
+ Requires-Dist: httpx; extra == "dev"
39
+ Requires-Dist: build; extra == "dev"
40
+ Requires-Dist: twine; extra == "dev"
41
+ Dynamic: license-file
42
+
43
+ # Adapt — The Adaptive File-Backed Web Server
44
+
45
+ Adapt is a lightweight, FastAPI-powered adaptive server that automatically turns files and Python modules into fully functional REST APIs.
46
+
47
+ Note: README vs Implementation
48
+ ----------------------------------
49
+ The `README.md` outlines the intended design and functionality. Some features are partially implemented, still in the roadmap, or only scaffolded in the repository. For a detailed list of known differences between README/spec and the current implementation, see `IMPLEMENTATION_NOTES.md` at the project root.
50
+ ---
51
+ Drop a CSV, Excel file, Markdown document, HTML page, Parquet-style dataset, audio/video file, or Python handler into a directory and Adapt instantly generates:
52
+
53
+ * CRUD API endpoints
54
+ * HTML DataTables UI (sortable, searchable)
55
+ * Inline editing with PATCH support
56
+ * HTTP streaming for audio/video files
57
+ * Media gallery UI with searchable cards
58
+ * Automatic schema inspection
59
+ * Safe writes via file locking
60
+ * Plugin-driven handlers
61
+ * Authentication, users, groups, and permissions
62
+ * API Keys for programmatic access
63
+ * Audit logging for security and compliance
64
+ * Health check endpoint for monitoring
65
+ * Row-Level Security (RLS) for granular data access
66
+ * Admin dashboard for managing users, groups, locks, caches, and keys
67
+
68
+ A backend that lives in a folder.
69
+
70
+ ---
71
+
72
+ ## Features
73
+
74
+ ### Adaptive File Discovery
75
+
76
+ On startup, Adapt:
77
+
78
+ * Scans the document root
79
+ * Detects supported files & handlers
80
+ * Builds REST routes
81
+ * Generates HTML table UIs for CSV/XLSX
82
+ * Generates media players and galleries for audio/video files
83
+ * Loads schema overrides and custom renderers
84
+ * Registers Python handlers automatically
85
+ * Serves all resources at extensionless URLs for cleaner access (e.g., `data.csv` → `/data`)
86
+ * Creates companion files in a hidden `.adapt` directory to avoid cluttering the docroot
87
+
88
+ No configuration required.
89
+
90
+ ---
91
+
92
+ ## Landing Page
93
+
94
+ Adapt provides a user-friendly landing page at the root URL (`/`) that serves as the entry point for authenticated users:
95
+
96
+ * **Welcome Message** - Introduction to Adapt and its capabilities
97
+ * **Quick Start Guide** - Step-by-step instructions for getting started
98
+ * **Accessible Resources** - Dynamic list of datasets, HTML pages, and Markdown documents the user can access based on their permissions
99
+ * **Media Gallery** - Browse and stream audio/video files
100
+ * **Admin Access** - Direct link to the admin dashboard for superusers
101
+
102
+ The landing page adapts to the user's authentication status and permissions, showing only resources they are authorized to view. For unauthenticated users, it displays public HTML and Markdown content.
103
+
104
+ ---
105
+
106
+ ## Automatic CRUD API
107
+
108
+ For CSV, Excel sheets, and Parquet datasets, Adapt exposes:
109
+
110
+ * `GET` — read items
111
+ * `POST` — create/append items
112
+ * `PATCH` — modify items
113
+ * `DELETE` — remove items
114
+ * `/schema` — JSON schema
115
+
116
+
117
+ ### Request Format for Dataset Endpoints
118
+
119
+ **Note:** For dataset resources (CSV, Excel, Parquet), API requests must use an envelope format specifying the action and data. This is required for all POST, PATCH, and DELETE requests.
120
+
121
+ **Envelope format:**
122
+
123
+ ```json
124
+ {
125
+ "action": "create|update|delete",
126
+ "data": [ ... ] // for create, or { ... } for update/delete
127
+ }
128
+ ```
129
+
130
+ **Examples:**
131
+
132
+ *Create rows (POST):*
133
+ ```json
134
+ {
135
+ "action": "create",
136
+ "data": [
137
+ {"id": "899", "name": "Unknown"},
138
+ {"id": "900", "name": "Alice"}
139
+ ]
140
+ }
141
+ ```
142
+
143
+ *Update a row (PATCH):*
144
+ ```json
145
+ {
146
+ "action": "update",
147
+ "data": {"_row_id": 1, "name": "Updated Name"}
148
+ }
149
+ ```
150
+
151
+ *Delete a row (DELETE):*
152
+ ```json
153
+ {
154
+ "action": "delete",
155
+ "data": {"_row_id": 2}
156
+ }
157
+ ```
158
+
159
+ This format is required for all dataset plugin endpoints. Future versions may support simpler payloads, but for now, always wrap your data in this envelope.
160
+
161
+
162
+ Each Excel **sheet** and Parquet file receives its own resource, enabling full CRUD operations per dataset. Parquet support is now robust and consistent with other dataset plugins, including atomic writes, schema inference, and safe concurrent editing.
163
+
164
+ For audio and video files, Adapt provides HTTP streaming endpoints using open standards for efficient playback, along with individual player pages and a searchable media gallery.
165
+
166
+ The plugin system is extensible, allowing any plugin to create sub-resources by setting a "sub_namespace" in the resource metadata, enabling hierarchical API routes for complex file formats.
167
+
168
+ ---
169
+
170
+ ## Caching System
171
+
172
+ Adapt now includes a robust, SQLite-backed caching system:
173
+
174
+ * GET responses for datasets, media metadata, and rendered content are cached for performance.
175
+ * Cache is stored in `DOCROOT/.adapt/adapt.db` and managed per resource.
176
+ * Plugins control what is cached and for how long (TTL).
177
+ * Cache is automatically invalidated on resource mutation (POST/PATCH/DELETE).
178
+ * Admin UI supports cache inspection and manual invalidation.
179
+
180
+ All major plugins (CSV, Excel, Parquet, HTML, Markdown, Media, Python handler) now support caching where appropriate. Parquet, CSV, Excel plugins use cache for reads and schema inference. Media plugin caches metadata. Python handler plugin does not cache routers (for safety).
181
+
182
+ Cache storage is configured at application startup, so plugin cache operations and Admin cache views use the same database path.
183
+
184
+ All cache expiry logic uses timezone-aware UTC datetimes.
185
+
186
+ Comprehensive test suite covers all cache logic and plugin integration.
187
+
188
+ ## Built-In HTML UIs (DataTables)
189
+
190
+ CSV and Excel datasets automatically generate a full-featured HTML UI:
191
+
192
+ * Sortable columns
193
+ * Search box
194
+ * Pagination
195
+ * Column hiding
196
+ * Responsive layout
197
+ * Automatic schema-based type formatting
198
+ * Inline editing (PATCH)
199
+ * Form-based row addition (POST)
200
+ * Row deletion (DELETE)
201
+ * **Common navigation bar** with links to API docs, admin dashboard (for superusers), dropdown of all discovered datasets, and logout
202
+
203
+ This UI is powered by DataTables and delivered via Jinja2 templates that extend a base template for consistent navigation. Companion files (`.adapt/*.index.html`) are generated during startup and can be customized by users to add features like charts, custom styling, or additional JavaScript. Rendering happens during requests to ensure dynamic data is always current.
204
+
205
+ Perfect for:
206
+
207
+ * Internal dashboards
208
+ * Quick data exploration
209
+ * Lightweight admin interfaces
210
+ * Local-first tools
211
+
212
+ ---
213
+
214
+ ## Media Gallery
215
+
216
+ Audio and video files automatically generate a Netflix/YouTube-style gallery UI:
217
+
218
+ * Card-based layout with file information, metadata, and video thumbnails
219
+ * Searchable by filename
220
+ * Direct streaming playback
221
+ * Responsive design
222
+ * Integrated with common navigation bar
223
+
224
+ Individual media files also have dedicated player pages with HTML5 video/audio elements for focused viewing. Streaming uses HTTP range requests for open-standard, efficient delivery. Metadata such as duration, bitrate, artist, and title are extracted and displayed where available.
225
+
226
+ Perfect for:
227
+
228
+ * Media libraries
229
+ * Content management
230
+ * Personal streaming servers
231
+ * Educational resources
232
+
233
+ ---
234
+
235
+ ## Python Handler Plugins (`*.py`)
236
+
237
+ Drop Python files into your doc root to auto-register custom FastAPI routes.
238
+
239
+ If the file defines an `APIRouter` named `router`:
240
+
241
+ ```python
242
+ from fastapi import APIRouter
243
+
244
+ router = APIRouter()
245
+
246
+ @router.get("/hello")
247
+ def hello():
248
+ return {"message": "Hello from a file handler!"}
249
+ ```
250
+
251
+ Adapt mounts it under:
252
+
253
+ ```
254
+ /api/<filename>/*
255
+ ```
256
+
257
+ This enables:
258
+
259
+ * Custom business logic
260
+ * Aggregation endpoints
261
+ * Integrations with external APIs
262
+ * Data transformations
263
+ * Secured/role-based logic layers
264
+
265
+ Without editing the core server.
266
+
267
+ ---
268
+
269
+ ## Safe Write Operations
270
+
271
+ Writes to CSV, Excel, and Parquet files follow a strict, atomic workflow:
272
+
273
+ 1. Permission check
274
+ 2. Acquire a file lock (with unique constraint to prevent race conditions)
275
+ 3. Write to a temporary file
276
+ 4. Atomic rename/move
277
+ 5. Release lock
278
+
279
+ **Lock Safety Features:**
280
+ * Database-level unique constraint prevents concurrent lock acquisition
281
+ * Automatic retry with exponential backoff (starting at 0.1s, doubling each attempt, capped at 1.0s, 30-second timeout)
282
+ * Stale lock cleanup on server startup (5-minute threshold)
283
+ * Lock expiration (5-minute TTL by default)
284
+
285
+
286
+ Parquet plugin now uses the same atomic write logic as CSV and Excel plugins, writing to a temporary file and atomically replacing the original, ensuring data integrity and safe concurrent access.
287
+
288
+ ---
289
+
290
+ ## Authentication & Authorization
291
+
292
+ Adapt includes a complete security layer for multi-user deployments:
293
+
294
+ ### Session-Based Authentication
295
+
296
+ * Cookie-based login system (HttpOnly, Secure, SameSite flags for comprehensive protection)
297
+ * PBKDF2 password hashing with per-user salts (100,000 iterations)
298
+ * 7-day session expiration with **active enforcement** and automatic cleanup
299
+ * Sliding session renewal - active sessions stay valid
300
+ * Background task removes expired sessions (runs daily)
301
+ * Timing attack mitigation with constant-time operations
302
+ * Automatic redirect to login for unauthenticated browser requests, followed by redirect to landing page after successful authentication
303
+ * JSON error responses for API clients
304
+
305
+ ### User Management
306
+
307
+ * Create and manage users via Admin UI or CLI
308
+ * Superuser role for administrative access
309
+ * Active/inactive user status
310
+ * Secure password storage (never plaintext)
311
+
312
+ ### Group-Based Permissions
313
+
314
+ * Organize users into groups (teams, departments, roles)
315
+ * Assign permissions to groups, not individual users
316
+ * Users inherit permissions from all their groups
317
+ * Supports complex organizational hierarchies
318
+
319
+ ### Resource-Level Permissions
320
+
321
+ * Granular control over dataset access
322
+ * Two permission types: `read` and `write`
323
+ * Permissions map to resource namespaces (e.g., `data`, `workbook/People`)
324
+ * Automatic enforcement on all dynamically generated routes
325
+ * Superusers bypass all permission checks
326
+
327
+ ### Permission Enforcement
328
+
329
+ All dataset routes (`/api/*`, `/ui/*`, `/schema/*`) are automatically protected:
330
+
331
+ 1. User must be authenticated (valid session cookie)
332
+ 2. User must have appropriate permission for the resource
333
+ 3. GET requests require `read` permission
334
+ 4. POST/PUT/PATCH/DELETE require `write` permission
335
+ 5. 403 Forbidden if permission denied
336
+
337
+ ### API Keys
338
+
339
+ * Programmatic access for scripts and external tools
340
+ * Generate keys via Admin UI or user Profile page with optional expiration (max 1 year)
341
+ * Authenticate via `X-API-Key` header
342
+ * Secure storage (SHA-256 hashed)
343
+ * Users can self-issue API keys for their own account
344
+
345
+ ### Audit Logging
346
+
347
+ * Records critical system actions for security and compliance
348
+ * Logs: Login/Logout, User/Group changes, Permission changes, API Key management
349
+ * Viewable and filterable via Admin UI
350
+
351
+ ### Row-Level Security (RLS)
352
+
353
+ * Plugins can enforce granular access control based on the authenticated user
354
+ * `filter_for_user` hook allows plugins to restrict data visibility
355
+ * Applied automatically during data retrieval
356
+
357
+ ---
358
+
359
+ ## Admin UI
360
+
361
+ Adapt ships with a built-in admin interface at `/admin/` to manage the entire security layer:
362
+
363
+ ### Users Tab
364
+
365
+ * Create new users with username and password
366
+ * Set superuser status
367
+ * Delete users
368
+ * View all registered users
369
+
370
+ ### Groups Tab
371
+
372
+ * Create groups with names and descriptions
373
+ * Manage group membership (add/remove users)
374
+ * Assign permissions to groups
375
+ * Delete groups
376
+
377
+ ### Permissions Tab
378
+
379
+ * Define new permissions (resource + action pairs)
380
+ * View all available permissions
381
+ * Delete unused permissions
382
+ * Assign permissions to groups
383
+
384
+ ### Locks Tab
385
+
386
+ * View current file locks
387
+ * Release stale locks
388
+ * Monitor concurrent access
389
+
390
+ ### API Keys Tab
391
+
392
+ * Generate new API keys for users (admin only)
393
+ * Users can self-manage their API keys via Profile page
394
+ * Revoke existing keys
395
+ * Set expiration dates (max 1 year)
396
+
397
+ ### Audit Logs Tab
398
+
399
+ * View chronological history of system actions
400
+ * Filter by user, action, or resource
401
+ * Inspect action details
402
+
403
+ ### Cache Tab
404
+
405
+ * View all cached entries with key, resource, expiration, and user
406
+ * Delete individual cache entries
407
+ * Clear all cache entries
408
+ * Monitor cache usage and performance
409
+
410
+ The Admin UI uses vanilla HTML/CSS/JavaScript for portability and simplicity—no build step required.
411
+
412
+ ---
413
+
414
+ ## Custom Overrides
415
+
416
+ Optional companion files customize behavior:
417
+
418
+ | File | Purpose |
419
+ | ----------------------------------- | --------------------------- |
420
+ | `.adapt/dataset.schema.json` | Override inferred schema |
421
+ | `.adapt/dataset.index.html` | Custom Jinja2 HTML template |
422
+ | `.adapt/dataset.<sheet>.html` | Sheet-level HTML override |
423
+ | `.adapt/dataset.<sheet>.schema.json`| Sheet-level schema override |
424
+
425
+ ---
426
+
427
+ ## Configuration
428
+
429
+ Adapt supports configuration via a `conf.json` file in `DOCROOT/.adapt/`. If the file doesn't exist, it's created with default values on first run.
430
+
431
+ The configuration allows customizing:
432
+
433
+ - `plugin_registry`: Map file extensions to plugin classes (e.g., add custom handlers).
434
+ - `host`: Bind host for `adapt serve`.
435
+ - `port`: Bind port for `adapt serve`.
436
+ - `tls_cert`: Path to TLS certificate file.
437
+ - `tls_key`: Path to TLS key file.
438
+ - `secure_cookies`: Whether to set secure flags on cookies.
439
+ - `readonly`: Enable read-only mode.
440
+ - `debug`: Enable debug logging.
441
+ - `logging`: Logging configuration dictionary for Python's dictConfig.
442
+
443
+ Precedence: explicit CLI flags > environment variables > `conf.json` > defaults.
444
+
445
+ Example `conf.json`:
446
+
447
+ ```json
448
+ {
449
+ "plugin_registry": {
450
+ ".custom": "my_plugin.CustomPlugin"
451
+ },
452
+ "host": "127.0.0.1",
453
+ "port": 8000,
454
+ "tls_cert": "/path/to/cert.pem",
455
+ "tls_key": "/path/to/key.pem",
456
+ "secure_cookies": true,
457
+ "readonly": false,
458
+ "debug": false,
459
+ "logging": {
460
+ "root": {
461
+ "level": "DEBUG"
462
+ }
463
+ }
464
+ }
465
+ ```
466
+
467
+ To reset, delete `conf.json` and restart the server.
468
+
469
+ ---
470
+
471
+ ## Plugin Registry & Companion Files
472
+
473
+
474
+ `AdaptConfig` embeds a `plugin_registry` that maps file extensions to dotted paths for the classes that own those datasets. The default registry wires `.csv`, `.xlsx`, and `.parquet` files to the built-in dataset plugins, all of which now use a consistent interface for schema inference, atomic writes, and safe editing. Parquet support is fully integrated and tested. Each plugin is responsible for producing the inferred JSON schema that becomes the companion `.adapt/*.schema.json`. Those companion files are generated once on server startup and never exposed directly over HTTP—they exist purely to inform the API responses, HTML UI rendering, and validation layers.
475
+
476
+ HTML companion files (`.adapt/*.index.html`) are generated as Jinja2 templates with pre-computed schema data (e.g., column headers) baked in, allowing for efficient rendering while supporting full customization. If a companion HTML file exists, it overrides the default UI template for that resource.
477
+
478
+ Plugins now have full control over route generation via the `get_route_configs` method. This allows plugins to define their own API, Schema, and UI endpoints, including injecting necessary context (like `api_url`) into UI templates. This architecture supports complex multi-resource files (like Excel workbooks) by allowing plugins to generate hierarchical routes using "sub_namespace" metadata.
479
+
480
+ ### Stability & Testing
481
+
482
+ The plugin system is backed by a strict interface contract (`adapt.plugins.base.Plugin`) and a comprehensive test suite. This ensures that custom plugins—whether for new file types or complex logic—integrate seamlessly with the core discovery and routing engines. The `ResourceDescriptor` acts as the immutable boundary between the file system and your code.
483
+
484
+ ## CLI Commands
485
+
486
+ The `adapt` CLI includes a few core commands:
487
+
488
+ * `adapt serve <root>` — serve the given document root (supports `--host`, `--port`, `--tls-cert`, `--tls-key`, `--reload`, `--readonly`, `--debug`).
489
+ * `adapt check <root>` — sanity-check the configuration, initialize `.adapt.db`, and print the discovered datasets.
490
+ * `adapt addsuperuser <root> --username <name>` — create a local superuser backed by `.adapt.db`.
491
+ * `adapt list-endpoints <root>` — show the automatically generated `/api/*`, `/ui/*`, and `/schema/*` paths for every resource.
492
+
493
+ ### Admin Commands
494
+
495
+ Adapt includes administrative commands for managing users, groups, and permissions:
496
+
497
+ * `adapt admin list-resources <root>` — list all discovered resources in the document root, including sub-namespaces for multi-resource files (e.g., Excel sheets).
498
+ * `adapt admin create-permissions <root> <resources>...` — create permissions and groups for specified resources (use `__all__` for all resources, including sub-namespaces).
499
+ * `adapt admin list-groups <root>` — display all groups with their associated permissions and assigned users.
500
+ * `adapt admin list-users <root>` — list local users.
501
+ * `adapt admin create-user <root> --username <name> [--password <pw>] [--superuser]` — create a user.
502
+ * `adapt admin delete-user <root> --username <name>` — delete a user.
503
+ * `adapt admin create-group <root> --name <group> [--description <text>]` — create a group.
504
+ * `adapt admin delete-group <root> --name <group>` — delete a group.
505
+ * `adapt admin add-to-group <root> --username <name> --group <group>` — add a user to a group.
506
+ * `adapt admin remove-from-group <root> --username <name> --group <group>` — remove a user from a group.
507
+
508
+ ## Installation
509
+
510
+ ```
511
+ pip install adapt-server
512
+ ```
513
+
514
+ Serve your directory:
515
+
516
+ ```
517
+ adapt serve ./data
518
+ ```
519
+
520
+ Runs on Uvicorn with TLS, RBAC, caching, locking, and adaptive routing.
521
+
522
+ ---
523
+
524
+ ## Example Directory Layout
525
+
526
+ ```
527
+ data/
528
+ employees.csv
529
+ employees.schema.json
530
+ sales.xlsx
531
+ sales.q1.html
532
+ video.mp4
533
+ audio.mp3
534
+ stats.py
535
+ readme.md
536
+ index.html
537
+ docs/
538
+ guide.md
539
+ ```
540
+
541
+ Adapt exposes:
542
+
543
+ * `/` — landing page with resource overview
544
+ * `/ui/employees` — DataTables UI
545
+ * `/api/employees` — CRUD API
546
+ * `/api/sales` — sheet listing
547
+ * `/api/sales/<sheet>` — CRUD API for each sheet
548
+ * `/media/video.mp4` — streaming endpoint
549
+ * `/ui/video.mp4` — media player page
550
+ * `/ui/media` — media gallery
551
+ * `/api/stats/*` — handler routes
552
+ * `/readme` — rendered Markdown content
553
+ * `/index` — HTML page content
554
+ * `/docs/guide` — rendered Markdown content
555
+ * `/admin/*` — admin UI
556
+
557
+ ---
558
+
559
+ ## Roadmap
560
+
561
+ * File watchers (hot-reload route generation)
562
+ * GraphQL auto-introspection
563
+ * Audit log browser in Admin UI (Completed)
564
+ * Plugin marketplace
565
+
566
+ ---
567
+
568
+ ## License
569
+
570
+ MIT License. See `LICENSE` file for details.
571
+
572
+ ---
573
+
574
+ # Adapt
575
+
576
+ Your filesystem is now an API platform.