Backend structure¶
The application package is koinon, installed from backend/src/koinon. Start the API with python -m koinon.serve, which selects the native pyfly server and event loop before the application lifecycle begins. The ASGI entry point remains koinon.main:app for embedding. Start the independent conversation worker with python -m koinon.assistants.worker.
Module responsibilities¶
| Module | Responsibility |
|---|---|
app.py |
Compose the native pyfly application context, security and API routes |
api/controllers |
Context, catalog, membership, audit and job HTTP endpoints |
catalog |
Knowledge hierarchy, persisted access grants and audit records |
knowledge |
Authorized document and dataset operations and domain bindings |
assistants |
Model configuration, agent scope, conversations, evidence and durable generation |
organization_chat |
One organization-wide chat default, scoped reads and revision-checked operator changes |
organization_people |
Tenant positions, organizational units, reporting lines, directory visibility and verified profile mappings |
storage |
Private attachment ports and deployment profiles; shared cloud transport lives in the independent koinon_storage package |
profiles |
User preferences, avatars and author summaries |
tokens |
Scoped personal API credentials, expiration and revocation |
jobs |
Persisted processing-job state and authorized job management; ingestion queue parity is tracked separately in qualification |
security |
OIDC settings, authentication and request identity |
operations |
Deployment configuration, resource limits and redacted observations |
web |
Shared route projection, error mapping, pagination and retained-domain admission |
Request schemas live in each context's dtos.py. Response mappers project persisted objects into the public response fields. Controllers validate HTTP input and call application services. Services enforce access and lifecycle rules, and repositories perform persistence operations through native pyfly Data.
Entities and repositories live in separate modules. The application reuses the same entity definitions for the API, workers and migrations, which keeps table metadata consistent. Migration execution remains a separate deployment operation with its own credentials.
The organization directory follows this layout with separate DTOs, entities, mappers, repositories, service and controllers. Native pyfly transactions own mutations. Fresh read-only authorization checks protect asynchronous directory projections against membership changes while an operation is waiting. Corporate positions and reporting relationships remain presentation data; security continues to use the verified principal and effective memberships. See People and organization.
Agent configuration and conversations¶
AssistantConfigurationService owns provider and agent changes, connection validation and configuration revisions. KnowledgeScopePolicy checks requested knowledge against persisted access and the agent's allowed resources. AssistantService owns private conversations and generation requests and delegates configuration operations to the focused service.
The queue claims work with a lease. Each consumer has its own worker identity, and expired workers lose authority to change a run. Admission limits apply to a user's queued and running answers within an organization, across conversations and retries. Replaying the same accepted request returns its existing run. See operator configuration for deployment limits and observations.
OrganizationChatService owns the organization default independently of conversations. The standard frontend resolves this setting using its current authorized workspace/project; explicit headless requests still submit the chosen agent identity. Configuration never grants knowledge access.
Original files and cloud transport¶
packages/storage/src/koinon_storage supplies typed Azure Blob Storage and Google Cloud Storage byte operations without importing the backend or either knowledge domain. The document, structured and attachment adapters retain their existing domain ports and keys. Optional provider SDKs and credentials are resolved lazily. PostgreSQL continues to own permissions, recorded digests, versions, expiry and provenance; the blob store owns the corresponding bytes.
For remote structured queries, the native executor materializes only registered pinned snapshots into bounded private temporary files before invoking DuckDB. Its SQL restrictions and disabled external access remain in force. See storage configuration and limits.
Stable contracts during refactoring¶
Moving a module preserves the public HTTP paths, SDK request shapes, canonical principals and existing storage identities. Encrypted provider credentials carry a format version: existing credentials keep their original key derivation, while newly written credentials use the current version. Keep backward reads until an explicit credential rotation has completed.
Integrators should use the typed SDK or public API. Internal entity and repository imports are implementation details and can change independently of those public contracts.