-
Notifications
You must be signed in to change notification settings - Fork 0
Structure
Provenance. Generated by
/n8-mapfrom the commit named below, and not regenerated since. Individual statements may have been overtaken by later work — most of the issues this map cites have since been fixed and closed. Read it as a snapshot of the codebase's shape, not as a current defect list; the GitHub issue register is authoritative for what is actually open. (The generating commit hash predates a history rewrite and no longer resolves.)
One-line summary: directory-by-directory map of the repo with the rule for adding to each location, the DB schema ownership table, and where tests for each area go.
Generated from commit 01f0f174 on 2026-08-31 by /n8-map.
Companion: Architecture (how the pieces work). Paths are repo-relative; line numbers as of the commit above.
| Path | What lives there | Rule for adding |
|---|---|---|
AutoNate.sln |
AutoNate.Web, AutoNate.Plugin.Abstractions, AutoNate.Web.Tests, AutoNate.E2E.Tests, AutoNate.Web.Tests.SamplePlugin, HelloPlugin, Auditor
|
New .NET project (incl. a plugin) must be added here to build with the solution. |
Directory.Build.props |
AnalysisLevel=latest, AnalysisMode=Recommended, EnforceCodeStyleInBuild, analyzers Microsoft.VisualStudio.Threading.Analyzers, AsyncFixer, SonarAnalyzer.CSharp; TreatWarningsAsErrors deliberately unset; no TFM (each csproj sets net10.0) |
Per-rule tuning goes in root .editorconfig, not here. |
Makefile |
infra-prepare/ensure/up/up-dashboard/down/reset/logs/ps, app (= app-dapr), rider-sidecar*, e2e-install, e2e
|
New dev workflow = new target here; compose services are addressed via COMPOSE := docker compose -f infra/docker-compose.yml. |
package.json, scripts/
|
Root Node tooling: scripts/vendor-bpmn.mjs (+ bpmn-entry.mjs) bundles bpmn-js into src/AutoNate.Spa/public/vendor/bpmn-js; scripts/regen-fa-icons.mjs regenerates src/AutoNate.Spa/src/lib/fa-icons.json
|
Repo-level build scripts only; SPA app code never goes here. |
CLAUDE.md, .claude/skills/
|
Project instructions + 10 skills (add-audit-event, add-page-context-provider, add-permission-gate, add-projection, add-record-event-type, add-workflow-execution-action, plugin-creator, mantine-*) |
Invoke the matching skill before touching its subsystem; fix drift you find in the same commit. Known drift: add-permission-gate step 6 references a non-existent usePermissionPrefetch; plugin-creator lists 8 of 13 IPluginContext members; add-page-context-provider claims a pageKey-mismatch 400 that no longer exists. |
.n8/ |
n8SDLC config (config.yml: areas api spa plugins services flowable infra ci docs tests), decisions.md, memory/audit-*.md, hot-paths.md
|
Append decisions; audit checklists are shared across audit runs. |
docs/ |
codebase/ (this map), plans/YYYY-MM-DD-kebab.md (design docs referenced from source comments), projection-framework/ (8 docs), samples/, mantine/llms.txt, playwright-test-plan.md, playwright-test-backlog.md
|
New design doc → docs/plans/<date>-<kebab>.md and reference it from the code it governs. |
infra/ |
docker-compose.yml (postgres, flowable, flowable-dapr, redis, nats, nats-init, dapr-placement, dapr-scheduler, hocuspocus, dapr-dashboard), dapr/components/{pubsub,statestore}.yaml (tracked source of truth), postgres/init/01-create-autonate-db.sql + 02-create-autonate-app-schema.sql, flowable/Dockerfile, scripts/bootstrap-jetstream.sh, ensure-up.sh, *-autonate-web-sidecar.sh, mounts/ (untracked runtime data) |
New infra service → compose + ensure-up.sh readiness + Makefile. New JetStream subject → also NatsStreamProvisioner.cs (they must match). executor sidecar is not in compose — add it if you need code nodes locally. |
src/ |
AutoNate.Web, AutoNate.Spa, AutoNate.Plugin.Abstractions
|
— |
plugins/ |
HelloPlugin/, Auditor/, shared Directory.Build.props/.targets, README.md
|
New plugin → plugins/<Name>/ (§6). |
services/ |
hocuspocus/ (Yjs sync edge, :1234), executor/ (NATS code runner) |
New sidecar → services/<name>/ with Dockerfile, README.md, package.json; wire into compose. |
flowable-extension/ |
Maven module com.autonate:autonate-flowable-events (Java 21) |
Java changes only; rebuilt by infra/flowable/Dockerfile. |
tests/ |
AutoNate.Web.Tests, AutoNate.E2E.Tests, AutoNate.Web.Tests.SamplePlugin
|
§8. |
temp/ (untracked) |
Scratch: screenshots, captured logs, Playwright snapshots | Anything throwaway goes here, never the repo root. |
| Path | What lives there | Rule for adding |
|---|---|---|
Program.cs (1636 lines) + Program.Partial.cs
|
All DI + pipeline + endpoint mapping (top-level statements). Registration blocks: cookie auth :87-137, CSRF threat model :151-194, audit/outbox/Dapr :195-262, DbContext :264-280, IDatabaseInitializer :281-285, authorization options :286, entity types :288-296, selector compilers :299-337, instance authorizers :339-348, IAuthorizer :350, content authz :351-383, stores :386-397, AQL entities :399-441, external connections :450-461, data stores/datasets/transformers/pipelines :463-614, agent skills :626-728, ISkillRegistry :730, page-query bridges :732-771, workflow behaviors :776-783, Yjs :784-796, AllowedHosts guard :798-823, system issues :824-895, hooks :897-906, plugin host :907-921, projections :946-992, cold tier :994-1003; app.Map*Endpoints() :1421-1487 |
Every new service is registered in the block for its area. Endpoint files are mapped in the :1421-1487 list — add app.Map<Thing>Endpoints(); there (content-hierarchy files are grouped after the :1467 comment). |
Endpoints/ (63 *Endpoints.cs + HttpContextActorExtensions.cs, SharedSecretEndpointFilter.cs, YjsInternalSecretEndpointFilter.cs, YjsManagedContentGuard.cs, UserDisplayName.cs) |
One file per route prefix; DTO records at top, public static class XEndpoints, MapXEndpoints(this IEndpointRouteBuilder app), MapGroup("/api/x").RequireAuthorization(), return app;
|
New endpoint file → Endpoints/<Thing>Endpoints.cs + app.Map<Thing>Endpoints(); in Program.cs:1421-1487. Every route gets one gate marker (RequirePermission/RequireKindPermission/AuthorizedInHandler/OpenToAuthenticated/AllowAnonymous) or AuthorizationGatePresenceTests fails. Mutations chain .DisableAntiforgery(); anonymous mutations must use an antiforgery token or a shared-secret filter. Emit view/mutation audit events via IAuditEventPublisher after success. |
Authorization/ |
EntityKinds.cs, Actions.cs, EntityTypeDefinition.cs, EntityRegistry.cs, SystemRoles.cs, AuthorizationOptions.cs, Edges/ (EdgeKinds, EntityEdgeWriter), EndpointFilters/ (RequirePermission*, RequireKindPermissionFilter, AuthorizationDecisionMetadata), EntityTypes/{CoreEntityTypes,AnalyticsEntityTypes}.cs, Evaluator/ (IAuthorizer, Authorizer, IInstanceAuthorizer, InstanceAuthorizers, FlowableInstanceAuthorizers, AuthCacheBumper), Selectors/ (parser, AST, printer, ISelectorCompiler, registry, per-kind compilers, PathOnlySelectorCompiler, RecordSelectorSqlCompiler, InMemorySelectorEvaluator) |
New EntityKind → const in EntityKinds.cs → EntityTypeDefinition in EntityTypes/CoreEntityTypes.cs (append to _all) or AnalyticsEntityTypes.cs → compiler in Selectors/<Kind>SelectorCompiler.cs (or PathOnlySelectorCompiler<T>) registered at Program.cs:299-337 → IInstanceAuthorizer in Evaluator/InstanceAuthorizers.cs registered at Program.cs:339-348 → bump tests/.../Authorization/EntityRegistryTests.cs:15 count → GrantsHelpModal.tsx text. New Action → const in Actions.cs + append to the kind's actions[]. |
Persistence/ |
AutoNateDbContext.cs (+ .DataStores.cs, .ProjectionCaches.cs partials), Scaffolded/ (77 EF entities), DatabaseSchemaInitializer.cs, PrimaryDatabaseInitializer.cs (Order 0), IDatabaseInitializer.cs, PersistenceModelMapper.cs, RecordPersistenceMapper.cs, DbConnectionFailureLoggingInterceptor.cs
|
New table → private const string <Feature>SchemaSql in DatabaseSchemaInitializer.cs + ExecuteSqlRawAsync line in EnsureAsync (:3746-3826) after its FK targets + entity class in Scaffolded/ + DbSet on the DbContext partial. Stores do NOT go here (see Services/). Secondary databases implement IDatabaseInitializer with Order 10. |
Services/<Area>/ (33 areas) |
Domain services, stores (EfCore<Thing>Store.cs next to I<Thing>Store.cs), event-type consts (<Area>EventTypes.cs), options classes |
New store → Services/<Area>/I<Thing>Store.cs + EfCore<Thing>Store.cs (primary-ctor IDbContextFactory<AutoNateDbContext>, AsNoTracking, ToModel()), AddScoped in Program.cs. New topic → <Area>EventTypes.cs with TopicRoot/TopicName consts, subject in Services/Nats/NatsStreamProvisioner.cs:53-105, transport + category in Services/Events/EventCatalog.cs. |
Services/Agent/ |
Loop/ (AgentSession, AgentOptions, SystemPromptBuilder, compaction), Skills/ (36 skills + IAgentSkill.cs, SkillRegistry.cs, Internal/ConfirmGate.cs, PluginContributedSkill.cs), Providers/ (IChatProvider, Anthropic/OpenAI, ChatProviderResolver), PageQuery/ (channels + routers — framework, do not touch per page), Conversations/, Catalog/ (agent models), Search/
|
New agent skill → Services/Agent/Skills/<Name>Skill.cs implementing IAgentSkill (globally unique tool names; JSON-schema JsonElement; authorize through IAuthorizer/gated stores; ConfirmGate for mutations) + builder.Services.AddScoped<IAgentSkill, <Name>Skill>(); at Program.cs:626-728 + tests in tests/AutoNate.Web.Tests/<Name>SkillTests.cs. |
Services/Events/ |
IAuditEventPublisher/DaprAuditEventPublisher, AuditEventOutbox.cs, AuditOutboxDispatcher.cs, EventCatalog.cs, ViewEventHelpers.cs, AuditContext.cs
|
New audit event → follow .claude/skills/add-audit-event; assert with factory.RecordedAuditEvents. |
Services/Records/ |
Record/type/edge/comment/history stores, Fields/ (IFieldType, FieldTypeRegistry, built-ins), RecordEventPublisher.cs, RecordSchemaEventTypes.cs, RecordFilterCompiler.cs, RecordTypeShortCodeCache.cs, Rollups/
|
New field type → Fields/<Name>FieldType.cs + registration. New record event type → .claude/skills/add-record-event-type. |
Services/Query/ |
AQL lexer/parser/AST/validator/executor, Entities/ (IQueryEntity, registry, 11 entities), saved queries, share tokens, suggestions |
New AQL entity → Services/Query/Entities/<Name>QueryEntity.cs + double registration at Program.cs:399-441 (AddScoped<X>() + AddScoped<IQueryEntity>(sp => sp.GetRequiredService<X>())). |
Services/Flowable/ |
IFlowableClient/FlowableClient, Cache/ (4 projections + polling feeds, FlowableReadThrough, retention, ColdTier/) |
New Flowable read path: extend IFlowableClient and tests/AutoNate.Web.Tests/StubFlowableClient.cs. |
Services/Workflow/ |
EfCoreWorkflowModelStore, WorkflowBpmnXml, IWorkflowSignalRegistry, Behaviors/ (WorkflowBehaviorRegistry, UnlockAccountBehavior, WorkflowBehaviorOptions), WorkflowEventTypes.cs, error/task recorders |
New built-in behavior → Behaviors/<Name>Behavior.cs : IWorkflowBehavior (idempotent) + AddSingleton<IWorkflowBehavior, X>() at Program.cs:776-783. |
Services/Signals/ |
DaprStreamingSubscriber, WorkflowSignalDispatcher
|
Always-on topic list at DaprStreamingSubscriber.cs:388-408. |
Services/BusWatcher/ |
BusWatcherStreamService, Subscriptions/ (SubscriptionManager, ChannelName, SubscriptionProtocol, Resolvers/, Gates/) |
New WebSocket channel → Resolvers/<X>ChannelResolver.cs + Gates/<X>ChannelSubscribeGate.cs + DI in ScopedSubscriptionsServiceCollectionExtensions.cs. |
Services/Projections/ |
Framework (IProjection, IChangeFeed, ChangeEvent, ProjectionWorker, registry/health/metrics/options, Stores/, Feeds/, BackfillRunner) |
New projection → follow .claude/skills/add-projection: projection class in the owning area (e.g. Services/Flowable/Cache/), cache table SQL, AddProjection<> + AddChangeFeed<> at Program.cs:946-992. |
Services/SystemIssues/ |
EfCoreSystemIssueStore, Detectors/ (PeriodicIssueDetector base + 10 detectors with nested *Options), Remediators/ (2), SystemIssueRemediationDispatcher, exception traps, CriticalIssueNotifier
|
New detector → Detectors/<Name>Detector.cs : PeriodicIssueDetector + options AddOptions<>().BindConfiguration() + AddHostedService<>() at Program.cs:846-878. New remediator → Remediators/<Name>Remediator.cs : IIssueRemediator + AddSingleton<IIssueRemediator, X>() at Program.cs:894-895. |
Services/Content/ |
IContentAuthorizer/ContentAuthorizer, ContentKinds, ProjectRole, IContentTreeService, IContentVersionService, Bindings/, attachment/import storage, ContentEventTypes.cs
|
New content kind must be added to ContentKinds, EntityKinds, the content_ancestors maintenance, and the ticket-kind map in Endpoints/YjsEndpoints.cs if collaborative. |
Services/Yjs/ |
YjsServerOptions (YjsServer:*), ticketing |
New Y-doc prefix → also services/hocuspocus/src/materializers.ts and YjsEndpoints.cs:724-731. |
Services/DataStores/, Services/Datasets/, Services/DataConnectors/, Services/Transformers/, Services/Analyzers/, Services/Pipelines/
|
Data platform (§9 of Architecture) |
New transformer → Services/Transformers/Builtin/<Name>Transformer.cs : ITransformer + AddSingleton<ITransformer, X>() at Program.cs:503-530 + entry in BuiltinSchemas.cs. New dataset parser → Services/Datasets/Files/<Kind>FileParser.cs : IDatasetFileParser + registry. New data-store kind → append DataStoreKind value, branch Endpoints/DataStoreEndpoints.cs:77, service under Services/DataStores/<Kind>/, extend IDatasetExecutor routing, DI at Program.cs:470-488. New pipeline node kind → PipelineNodeKinds + Pipelines/Execution/<Kind>Runner.cs : INodeRunner. |
Services/Menus/, Services/SiteSettings/
|
EfCoreMenuStore, EfCorePageTemplateStore, PageRegistrySnapshotCache; SiteSettingsRegistry, SiteSettingsStore, SiteAppearanceSnapshotCache
|
New site setting → declare in Services/SiteSettings/SiteSettingsRegistry.cs. New page template row → seed SQL in DatabaseSchemaInitializer.cs (PageTemplatesSeedSql, :1325) + SPA key (§3). |
Services/Auth/, Services/Authorization/, Services/Audit/, Services/Notifications/, Services/ExternalConnections/, Services/Forms/, Services/Dashboards/, Services/Notes/, Services/Nats/, Services/Dapr/, Services/SystemHealth/, Services/ApplicationEvents/, Services/Common/
|
Local users + auth events; role/group/assignment/grant stores + IAM events; IRequestContext; notifications + listener; connection store + secret protector; forms; dashboards; markdown→BlockNote; NatsStreamProvisioner; sidecar probe; health probes; app events; helpers |
Follow the store pattern; new ISystemHealthProbe → Services/SystemHealth/. |
Hooks/ |
HookRegistry<T>, ActionHub, FilterHub, HookRegistrar, ScopedHookRegistrar, HookSubscription
|
New hook point → const in src/AutoNate.Plugin.Abstractions/HookPoints.cs + host call site guarded by HasAction/HasFilter; document payload type in the abstractions. |
Plugins/ |
PluginRuntime, PluginHostedService, PluginAssemblyLoadContext (shared-assembly list), PluginManagementService, PluginUploadValidator, PluginManifest, PluginSchemaProvisioner, PluginMigrationRunner, PluginDataAccess*, Plugin{Menus,Behaviors,Projections,AgentSkills,Connectors,Transformers} + Noop*, PluginScheduledJob*, SafePluginServiceProvider, PluginOptions
|
New plugin extension surface → abstraction interface in AutoNate.Plugin.Abstractions, host impl + Noop* here, wire into PluginContext and the enable/disable sweep in PluginRuntime.cs:214-243. |
Models/ |
Hand-written domain models: Records/, Authorization/, Forms/, Menus/, Notifications/, FlowableModels.cs, WorkflowModel.cs, LocalUser.cs
|
Domain model here; EF entity in Persistence/Scaffolded/; mapper in Persistence/*Mapper.cs. |
Configuration/, Storage/
|
InfrastructureOptions (Flowable, Dapr), NatsOptions, TrustedProxyOptions, DevelopmentAutoLoginOptions; DataOptions (Data:Root, Data:PublicUrlPrefix=/files), IDataPaths/DataPaths
|
New writable runtime folder → property on IDataPaths created in the DataPaths ctor, under /data. |
appsettings.json, appsettings.Development.json
|
Dev defaults; production overrides via env vars (README "Deployment configuration") | New options class → AddOptions<T>().BindConfiguration(T.SectionName); add dev value here. |
wwwroot/ |
Vite dist/ copy (Release/publish) + drawio/ static assets |
Never edit by hand; BuildSpa target owns it. |
data/ |
Runtime /data root in dev (datastores, plugins, repositories, tmp, uploads, wwwroot, datastores-writer.secret) |
Gitignored runtime state. |
Each row is a private const string at the given line, executed in EnsureAsync (:3746-3826) in this order unless noted. "Owns" = tables created there.
| Line | Section const | Owns (tables) |
|---|---|---|
| 9 | WorkflowVersioningSql |
workflow_model_versions (+ workflow_models columns) |
| 112 | WorkflowDefaultVariablesSql |
column adds |
| 118 | RecordsSchemaSql |
record_types, record_type_fields, record_type_audit_log
|
| 171 | RecordsDataSchemaSql |
records, record_field_changes
|
| 250 | RecordsEdgesSchemaSql |
record_edge_types, record_edge_type_fields, record_edges
|
| 305 | RecordsCommentsSchemaSql |
record_comments, record_comment_revisions
|
| 338 | RecordWatchesSchemaSql |
record_watches |
| 354 | AuthorizationSchemaSql |
entity_kinds, entity_edges, roles, role_assignments, auth_cache_version, auth_seed_state, groups, group_members, permission_grants
|
| 489 / 574 / 605 / 632 |
RecordEdgeBackfillSql, RecordEdgeShadowBackfillSql, EntityEdgeHotIndexesSql, RolePermissionsToGrantsSql
|
one-shot backfills (gated by auth_seed_state) |
| 537 | SuperAdminBackfillSql |
conditional on Authorization:AssignSuperAdminToAllExistingUsers
|
| 663 / 698 |
PageTemplatesSchemaSql, PageTemplatesPluginColumnsSql (after PluginsSchemaSql) |
page_templates (+ plugin columns) |
| 727 | MenusSchemaSql |
menus, menu_items, status_appearance_entries, site_appearance_settings
|
| 1057 / 1104 / 1212 / 1264 |
IconMenuWrapSettingsSql, SiteConfigSiteInformationSql, SiteConfigSystemHealthSql (after PageTemplatesSeedSql), SiteConfigStatusAppearanceSql
|
site-config menu seeds |
| 1325 / 1441 |
PageTemplatesSeedSql, PageTemplatesThumbnailSeedSql
|
built-in page_templates rows |
| 1479 |
MenuItemsPluginColumnSql (after PluginsSchemaSql) |
menu_items.created_by_plugin_id |
| 1502 / 1538 / 1571 / 1598 |
PluginsSchemaSql, PluginDataIsolationSql, PluginsIconMenuRemovalSql, PluginsSiteConfigMenuSql
|
plugins (+ code, role_password_encrypted), role plg_readers, menu seeds |
| 1660 / 1684 |
WorkflowExecutionErrorsSql, WorkflowTaskCompletionsSql
|
workflow_execution_errors, workflow_task_completions
|
| 1701 / 1714 / 1753 |
SiteSettingsSql, NotificationsSql, LocalUserLockoutSql
|
site_settings, notifications, local_users lockout columns |
| 1770 / 1794 |
AuditOutboxSchemaSql, AuditOutboxDeadLettersSchemaSql
|
audit_outbox, audit_outbox_dead_letters
|
| 1820 / 1876 |
SystemIssuesSchemaSql, SiteConfigSystemIssuesSql
|
system_issues + menu seed |
| 1953 / 2043 / 2262 |
SiteConfigFormsSql, SiteConfigChatbotSettingsSql, SiteConfigChatbotModelsMenuSql
|
menu seeds |
| 2113 | FormsSchemaSql |
forms, form_versions
|
| 2165 | ExternalConnectionsSchemaSql |
external_connection |
| 2200 / 2444 |
AgentConversationsSchemaSql, AgentMessageSummaryColumnsSql
|
agent_conversation, agent_message, agent_tool_call
|
| 2315 / 2346 / 2382 |
AgentModelCatalogSchemaSql, AgentModelCatalogSeedSql, AgentModelDefaultAvailableColumnsSql
|
agent_model |
| 2466 / 2632 / 2673 / 2705 |
ContentHierarchySchemaSql, ContentLocatorSchemaSql, ContentNotePageIndexSql, NotePreviewSvgSql
|
projects, project_members, cabinets, notebooks, pages, page_versions, page_attachments, notes, note_versions, content_ancestors (+ locator columns) |
| 2723 / 2873 |
ContentDocumentsSchemaSql, DocumentsMenuItemSeedSql
|
folders, documents, document_versions, document_comments, document_bindings
|
| 2931 / 2950 / 2965 |
PageFavoritesSchemaSql, YjsDocumentsSchemaSql, ContentSampleProjectSeedSql
|
page_favorites, yjs_documents, sample project |
| 3020 | DashboardsSchemaSql |
dashboards, dashboard_widgets, dashboard_shares
|
| 3092 / 3122 / 3169 |
SavedQueriesSchemaSql, QueryMenuSeedSql, DataMainMenuSeedSql (runs last) |
saved_queries + menu seeds |
| 3242 | ProjectionFrameworkSchemaSql |
projection_versions, projection_watermarks
|
| 3271 / 3379 / 3415 / 3430 |
WorkflowCacheSchemaSql, WorkflowEventLogSchemaSql, ProcessRetentionConfigSchemaSql, RecordActivityRollupSchemaSql
|
workflow_execution_cache, workflow_task_cache, workflow_variable_cache, workflow_event_log_cache, process_retention_config, record_activity_rollup_cache
|
| 3454 / 3564 / 3611 |
DataStoresSchemaSql, DatasetsSchemaSql, SavedQueryShareTokensSchemaSql
|
datastores, dataconnectors, datastore_files, datastore_tables, connector_runs, datasets, saved_query_share_tokens
|
| 3645 / 3719 |
PipelinesSchemaSql, CodeTransformersSchemaSql
|
pipelines, pipeline_runs, pipeline_run_steps, code_transformers
|
Not owned here: local_users base table (infra/postgres/init/02-create-autonate-app-schema.sql), per-plugin plg_<code>.* (runtime Plugins/PluginSchemaProvisioner.cs + plugin migrations/*.sql), autonate_datastores schemas ds_<id> / cache_<id> (Services/DataStores/Sql/, Services/Datasets/Cached/).
Config at project root: vite.config.ts (@ → src/, dev proxy for /api /account /dapr /bus-watcher /files + ws /ws/bus-watcher, /ws/agent-model-default to ASPNETCORE_URL ?? http://localhost:5108), tsconfig.app.json (strict), eslint.config.js, package.json scripts dev build type-check lint. No vitest, no Playwright JS config — browser tests are .NET (§8).
| Path | What lives there | Rule for adding |
|---|---|---|
main.tsx |
Provider order QueryClientProvider > SiteAppearanceProvider > MantineRoot > ModalsProvider > BrowserRouter > (Notifications, Router); imports @fortawesome/fontawesome-free/css/all.css, index.css, widgets.css
|
Global providers only. |
router.tsx |
AuthShell (login), full-bleed routes outside the shell (/documents/edit/:id, /documents/preview/:id, anonymous /q/:token), AppShell → renderAppRoutes() + path="*" → DynamicPageRoute
|
Only add a route here if it must render outside AppShell. |
routes/appRoutes.tsx |
APP_ROUTES (:124) — parameterized routes and layout shells only; CONFIG_TEMPLATE_ANCHORS (:72) for admin/config/*; protect() wrapper; findCollidingAppRoute, anchorPathForTemplateKey used by the menu editor |
New parameterized page → entry in APP_ROUTES wrapped in protect(<X />); lazy-load heavy pages with lazy() + Suspense (pattern :18-36). New config section → CONFIG_TEMPLATE_ANCHORS + PAGE_TEMPLATES key + pages/admin/config/sections.tsx export. |
pageTemplates.tsx |
PAGE_TEMPLATES: Record<string, ReactElement> (:52-92); keys match page_templates.key; side-effect import "@/widgets"
|
New menu-placeable page → pages/<area>/<Page>.tsx + key here + page_templates seed row (DatabaseSchemaInitializer.cs:1325) so an admin can place it on a menu. |
pages/<area>/ |
One folder per feature: admin/ (Roles Groups Grants Hierarchy Explain Plugins Projections + config/ sections, datastores/ datasets/ dataconnectors/ pipelines/ code-transformers/), bus-watcher/, dashboard/, documents/, dynamic-page/, edge-types/, forms/, home/, login/, manage-users/, not-found/, notes/ (31 files), notifications/, query/, record-types/, records/, user-profile/, workflow/, workflow-executions/, workflow-tasks/
|
Page + its private sub-components, co-located .css, zod schemas (userSchemas.ts), and use<Page>PageContext.ts all live in the page folder. |
api/<domain>.ts (44) + api/client.ts
|
axios instance (withCredentials, rejects HTML on /api, 401 → /?returnUrl=); one module per backend prefix with const BASE = "/api/<x>" and (params, signal?) functions |
New API client → api/<domain>.ts; never call axios directly from a page. |
hooks/use<Domain>.ts (38) |
TanStack Query v5 hooks; key factories ["domain", "op", ...args] as const; useQuery({ queryFn: ({ signal }) => fn(params, signal) }); live invalidation via useBusSubscription, useInvalidateOnChannels
|
Pair every api/<domain>.ts with hooks/use<Domain>.ts. Permission checks: usePermissionChecks + permissionKey (hooks/usePermissionChecks.ts). |
types/ |
Shared DTO types (menus.ts, records.ts, flowable.ts, siteAppearance.ts, statusAppearance.ts) |
Cross-page DTOs only. |
components/ |
Shared: data-table/DataTable.tsx (DataTableColumn<T>, wraps mantine-datatable), PageHeader.tsx, ConfirmModal.tsx, IconPicker.tsx, ColorPicker.tsx, AssigneePicker.tsx, SelectorBuilder.tsx, CronExpressionBuilder.tsx, JsxCodeEditor.tsx, JsxFormHost.tsx, SiteBrand.tsx; subfolders agent/ aql-editor/ documents/ notifications/ picker/ workflow/
|
Component used by >1 page → here (subfolder if >1 file). Tables go through DataTable; forms use useForm + zod4Resolver as zodResolver from mantine-form-zod-resolver with mode: "controlled"; tooltips use Mantine Tooltip; feedback via `notifications.show({ message, color: "green" |
widgets/ |
Dashboard widget registry (registry.ts: registerWidget, WidgetDefinition<TConfig> with zod schema), index.ts (one import per widget), AutoConfigForm.tsx, dataSource.ts, DataSourcePicker.tsx, widget folders data-table/ mantine-chart/ quadrant-chart/ composite-chart/
|
New widget → widgets/<name>/<Name>Widget.config.ts (schema + registerWidget), <Name>Widget.tsx, optional <Name>ConfigForm.tsx, + one import line in widgets/index.ts. CSS in widgets.css. |
agent/ |
AgentSidebar.tsx (+ .css), AgentSidebarContext.tsx, AgentChatTrigger.tsx, ChatPaletteModal.tsx, api.ts, useAgentStream.ts, usePageKey.ts, pageContext/{PageContextRegistry.tsx,forms.ts,types.ts}
|
Framework — do not edit per page. New page-context provider → pages/<area>/use<Page>PageContext.ts calling useRegisterPageContext({ pageKey, getSnapshot, onPageQuery?, actions?, onPageAction? }); add the pageKey pattern to agent/usePageKey.ts; follow .claude/skills/add-page-context-provider. |
shell/ |
AppShell.tsx (Mantine AppShell, header 56px, AgentSidebar sibling), AuthShell.tsx, NavMenu.tsx (menus main/icon/user), ProtectedRoute.tsx (auth-only), headerStyles.ts, shell.css
|
Header chrome uses --app-* vars via headerStyles.ts. |
lib/ |
Non-React utilities: siteAppearance.ts (applySiteAppearanceToDocument), statusAppearance.ts, faIcons.ts + fa-icons.json, blocknote/ (schemas, noteEmbedBlock), bpmn/, cron/, ws/ (subscription client), yjs/ (useYjsDocument, useBlockNoteWithYjs, YjsEditor, Excalidraw/draw.io hooks, ticket.ts) |
Pure helpers and editor integrations. |
providers/, preferences/, menus/
|
MantineRoot.tsx (static theme), SiteAppearanceProvider.tsx; UserPreferencesContext.tsx + PreferencesModal.tsx; resolveItemPath.ts
|
— |
index.css, widgets.css
|
Global + surviving custom widget styles (.row-archived, .notification-unread, ManageUsers avatars) |
Prefer Mantine props; never re-add --bs-*, bi-*, form-control, panel-*. |
IAutoNatePlugin.cs, IPluginContext.cs, IHookRegistrar.cs / IActionHub.cs / IFilterHub.cs / HookHandle.cs / HookPoints.cs, IPluginMenus.cs, IPluginBehaviors.cs + IWorkflowBehavior.cs + BehaviorContext/Result/VariableValue.cs, IPluginProjections.cs, IPluginAgentSkills.cs, IPluginConnectors.cs + IPluginDataConnector.cs, IPluginTransformers.cs + IPluginTransformer.cs + DataFrame.cs, IPluginDataAccess.cs, AuditEventNotification.cs, AuthorizeFilterContext.cs, PluginDataRequest.cs. Rule: only JsonElement/primitives/these DTOs cross the ALC boundary; adding a member here is a contract change for every plugin — add the host impl + Noop* in src/AutoNate.Web/Plugins/ in the same commit, and keep PluginAssemblyLoadContext.SharedAssemblies ⇔ plugins/Directory.Build.targets exclusions in lockstep.
| Path | Contents | Rule |
|---|---|---|
services/hocuspocus/ |
src/{index,auth,persistence,webhook,materializers,noteEmbedStub}.ts, Dockerfile, README.md; env HOCUSPOCUS_PORT=1234, YJS_INTERNAL_SHARED_SECRET, AUTONATE_WEB_URL, Postgres |
New collaborative doc prefix → materializers.ts:283-305 switch + host YjsEndpoints.cs ticket mapping; fragment name must match the SPA hook. |
services/executor/ |
src/{index,jsRunner,pythonRunner,pythonWorker,pythonProtocol,wire}.ts + test/*.test.mjs (npm test); NATS pipeline-code-run.> core queue subscriber (queue group executor) executor; isolated-vm (js) / pyodide (python) |
Wire format is Pipelines/Execution/CodeNodeWireFormat.cs on the host — change both. |
Skeleton: <Name>.csproj (empty SDK project; plugins/Directory.Build.props supplies net10.0, <Private>false</Private> abstractions reference, and copies plugin.json, migrations/*.sql, PageTemplates/*.template|*.png to output), <Name>.cs : IAutoNatePlugin, plugin.json (name version entryAssembly [entryType] [templates]), migrations/NNN_*.sql (lexical order, tracked in plg_<code>.__plugin_migrations), PageTemplates/. Build → dist/<Name>.zip via plugins/Directory.Build.targets (AfterTargets="Build"); upload at /admin/plugins. Add the project to AutoNate.sln. Reference: plugins/Auditor/Auditor.cs:43-65 (action + data-view filter hooks). Never ship AutoNate.Plugin.Abstractions.dll, Npgsql.dll, Dapper.dll, or Microsoft.Extensions.*.Abstractions.dll in the zip. Follow .claude/skills/plugin-creator (note its IPluginContext member list is incomplete — see IPluginContext.cs).
pom.xml (Flowable 8, Spring Boot 4, Java 21), src/main/java/com/autonate/flowableevents/ (auto-configuration, two event listeners, DaprWorkflowEventPublisher, AutoNateBehaviorDelegate, DueDateHelper, script-task support), src/main/resources/META-INF/spring/…AutoConfiguration.imports, src/test/java/… (5 test classes). Built and tested inside infra/flowable/Dockerfile (mvn --batch-mode test package). Do not rename the autonateBehaviorDelegate bean; config keys are autonate.flowable-events.* (compose sets AUTONATE_FLOWABLE_EVENTS_*).
Run: cd infra && docker compose -p infra up -d postgres nats nats-init redis then dotnet test AutoNate.sln (~8 min); E2E via make e2e.
| Project | Fixture | Naming / placement |
|---|---|---|
tests/AutoNate.Web.Tests/ (169 files) |
AutoNateWebApplicationFactory.cs (WebApplicationFactory<Program>, async CreateAsync(extraConfig), fresh autonate_test_<guid> DB per factory via PostgresTestDatabase.cs, dev auto-login as admin, authorization off, detectors/remediation/projection worker/retention off, AUTONATE_ALLOW_RUNNING_WITHOUT_DAPR=true; swaps StubFlowableClient, RecordingAuditEventPublisher, RecordingRecordEventPublisher) |
Endpoint tests <Area>EndpointsTests.cs (root); store tests EfCore<Thing>StoreTests.cs; event contracts <Domain>EventPublishingTests.cs; detectors <Detector>Tests.cs; skills <Name>SkillTests.cs; [Trait("Category","Integration")] on DB-touching classes. Subfolders: Authorization/ (44: *EnforcementTests.cs pass ["Authorization:Enabled"]="true", ["Authorization:Enforcement"]="full"; AuthorizationGatePresenceTests, SelectorParserTests, AuthorizerTests, ContentAuthorizerPolicyTests…), Query/ (AQL lexer/parser/endpoints), Hooks/, Plugins/ (PluginLoaderTests against the staged SamplePlugin, PluginDataIsolationTests), Workflow/, Datasets/, Storage/. New area with >3 files → its own subfolder + namespace AutoNate.Web.Tests.<Folder>. |
tests/AutoNate.E2E.Tests/ (29 test classes) |
AutoNateE2EFixture.cs (collection fixture "AutoNate E2E"; boots AutoNate.Web as a child process with BuildSpa=true on a random port against a recreated AutoNate_E2E DB; Playwright chromium), Support/{E2ETestBase,ApiSeeder,ConsoleErrorGuard,TestNames}.cs
|
One <Area>Tests.cs per feature (RecordsCrudTests, NotesTests, DocumentEditorTests, PipelinesAdminTests, AgentSidebarTests, PermissionGatingTests, …). This is the only SPA test surface — pipelines/transformers have no unit tests, only E2E. Plan/backlog: docs/playwright-test-*.md. |
tests/AutoNate.Web.Tests.SamplePlugin/ |
SamplePlugin.cs, plugin.json; staged into AutoNate.Web.Tests/bin/.../test-plugins/SamplePlugin/ by the test csproj |
Extend when a plugin-host feature needs a real ALC round-trip. |
flowable-extension/src/test/java/… |
JUnit 5 | Java changes need a test here; runs inside the image build. |
Area → test location quick map: endpoints/stores/events → AutoNate.Web.Tests/*Tests.cs; authorization/selectors/enforcement → AutoNate.Web.Tests/Authorization/; AQL → AutoNate.Web.Tests/Query/; hooks/plugins → AutoNate.Web.Tests/Hooks/, Plugins/; workflows → root Workflow*Tests.cs + Workflow/; projections → root ProjectionFramework*Tests.cs; system issues → root SystemIssue*Tests.cs + <Detector>Tests.cs; agent → root Agent*Tests.cs, *SkillTests.cs; content → root ContentTreeServiceTests.cs, Phase6/7*Tests.cs + Authorization/{Content,Document,Folder}*Tests.cs; data platform → root DataStore*Tests.cs, Datasets/; anything browser-visible → AutoNate.E2E.Tests/<Area>Tests.cs.
Getting started
Using Auton8
- Records
- Workflows
- Documents-and-Notes
- Queries-and-Dashboards
- Data-Stores-and-Pipelines
- The-Assistant
- Administration
Building Auton8
Repository