spine-framework 0.3.124 → 0.3.126
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.
- package/.framework/cli/commands/agents.ts +35 -37
- package/.framework/cli/commands/auth.ts +35 -34
- package/.framework/cli/commands/create-app.ts +104 -40
- package/.framework/cli/commands/dev.ts +104 -69
- package/.framework/cli/commands/doctor.ts +179 -69
- package/.framework/cli/commands/generate.ts +83 -143
- package/.framework/cli/commands/init.ts +72 -34
- package/.framework/cli/commands/install-app.ts +260 -125
- package/.framework/cli/commands/items.ts +33 -44
- package/.framework/cli/commands/migrate.ts +122 -40
- package/.framework/cli/commands/migrations.ts +33 -40
- package/.framework/cli/commands/pipelines.ts +31 -39
- package/.framework/cli/commands/status.ts +47 -23
- package/.framework/cli/commands/system.ts +47 -37
- package/.framework/cli/commands/test.ts +112 -68
- package/.framework/cli/commands/validate-app.ts +215 -121
- package/.framework/cli/context.ts +112 -130
- package/.framework/cli/env-loader.ts +47 -18
- package/.framework/cli/index.ts +81 -42
- package/.framework/docs/runtime-types.md +1024 -0
- package/.framework/functions/_shared/agent-runner.ts +1296 -961
- package/.framework/functions/_shared/app-manifest.ts +82 -68
- package/.framework/functions/_shared/audit.ts +135 -83
- package/.framework/functions/_shared/{cil-state.ts → cil.ts} +158 -56
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +224 -335
- package/.framework/functions/_shared/kb.ts +319 -0
- package/.framework/functions/_shared/llm.ts +92 -0
- package/.framework/functions/_shared/logging.ts +288 -0
- package/.framework/functions/_shared/middleware.ts +329 -365
- package/.framework/functions/_shared/outcomes.ts +36 -0
- package/.framework/functions/_shared/permissions.ts +359 -643
- package/.framework/functions/_shared/pipeline-runner.ts +243 -316
- package/.framework/functions/_shared/principal.ts +376 -468
- package/.framework/functions/_shared/resolve-credentials.ts +102 -0
- package/.framework/functions/_shared/resolve-ids.ts +188 -16
- package/.framework/functions/_shared/retry-deliveries.ts +104 -0
- package/.framework/functions/_shared/schema-utils.ts +611 -373
- package/.framework/functions/_shared/testing.ts +207 -137
- package/.framework/functions/_shared/tracing.ts +276 -0
- package/.framework/functions/_shared/trigger-engine.ts +159 -211
- package/.framework/functions/_shared/webhook-registration.ts +95 -81
- package/.framework/functions/_shared/webhook-registry.ts +153 -75
- package/.framework/functions/account-nodes.ts +31 -53
- package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
- package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
- package/.framework/functions/adapters/openai-outbound.ts +40 -0
- package/.framework/functions/admin-data.ts +685 -537
- package/.framework/functions/admin-funnel.ts +31 -20
- package/.framework/functions/admin-install-funnel.ts +47 -28
- package/.framework/functions/admin-signals.ts +47 -29
- package/.framework/functions/ai-agents.ts +122 -147
- package/.framework/functions/ai-interactions.ts +180 -90
- package/.framework/functions/api-keys.ts +250 -192
- package/.framework/functions/apps.ts +203 -197
- package/.framework/functions/auth.ts +98 -91
- package/.framework/functions/cil-agent-ingest.ts +773 -0
- package/.framework/functions/cil-agent.ts +592 -0
- package/.framework/functions/cil-callmap.ts +1227 -0
- package/.framework/functions/cil-config.ts +583 -0
- package/.framework/functions/cil-context.ts +445 -0
- package/.framework/functions/cil-doc.ts +1752 -0
- package/.framework/functions/cil-embeddings.ts +1202 -0
- package/.framework/functions/cil-graph.ts +585 -0
- package/.framework/functions/cil-ingest.ts +2416 -0
- package/.framework/functions/cil-pipeline.ts +318 -0
- package/.framework/functions/cil-project.ts +499 -0
- package/.framework/functions/cil-validate.ts +469 -0
- package/.framework/functions/debug-auth.ts +73 -53
- package/.framework/functions/deliveries.ts +117 -0
- package/.framework/functions/embeddings.ts +528 -516
- package/.framework/functions/eval-harness.ts +158 -106
- package/.framework/functions/integration-outbound.ts +311 -0
- package/.framework/functions/integration-routes.ts +240 -466
- package/.framework/functions/integrations.ts +132 -140
- package/.framework/functions/invites.ts +401 -201
- package/.framework/functions/item-progress.ts +113 -53
- package/.framework/functions/kb.ts +28 -0
- package/.framework/functions/logs.ts +239 -222
- package/.framework/functions/observability.ts +308 -259
- package/.framework/functions/pipeline-executions.ts +179 -235
- package/.framework/functions/pipelines.ts +163 -205
- package/.framework/functions/prompt-configs.ts +109 -156
- package/.framework/functions/roles.ts +97 -147
- package/.framework/functions/system-cron.ts +132 -218
- package/.framework/functions/system.ts +112 -52
- package/.framework/functions/tests.ts +32 -28
- package/.framework/functions/timers.ts +162 -210
- package/.framework/functions/triggers.ts +282 -346
- package/.framework/functions/types.ts +283 -400
- package/.framework/migrations/001_core_schema.sql +630 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
- package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
- package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
- package/.framework/migrations/005_core_observability.sql +598 -0
- package/.framework/migrations/006_security_hardening_rls.sql +97 -0
- package/.framework/migrations/007_kb_article_list.sql +237 -0
- package/.framework/migrations/008_items_target.sql +8 -0
- package/.framework/migrations/009_roles_slug_unique.sql +11 -0
- package/.framework/public/spine.config.json +91 -0
- package/.framework/scripts/app-install-cli.ts +112 -98
- package/.framework/src/App.tsx +67 -20
- package/.framework/src/apps/admin/index.tsx +97 -27
- package/.framework/src/components/AppWrapper.tsx +50 -11
- package/.framework/src/components/CustomAppLoader.tsx +131 -22
- package/.framework/src/components/admin/AdminListPage.tsx +75 -8
- package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
- package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
- package/.framework/src/components/admin/PageInstructions.tsx +49 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
- package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
- package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
- package/.framework/src/components/app-sidebar.tsx +50 -3
- package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
- package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
- package/.framework/src/components/kb/KBArticleList.tsx +557 -0
- package/.framework/src/components/layout/AppShell.tsx +54 -16
- package/.framework/src/components/layout/Header.tsx +50 -38
- package/.framework/src/components/layout/Layout.tsx +48 -32
- package/.framework/src/components/layout/Sidebar.tsx +167 -16
- package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
- package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
- package/.framework/src/components/runtime/DataFilters.tsx +78 -1
- package/.framework/src/components/runtime/DataHeader.tsx +32 -29
- package/.framework/src/components/runtime/DataListPage.tsx +161 -2
- package/.framework/src/components/runtime/DataStats.tsx +48 -1
- package/.framework/src/components/runtime/DataTable.tsx +153 -1
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
- package/.framework/src/components/runtime/index.ts +16 -9
- package/.framework/src/components/search-form.tsx +33 -1
- package/.framework/src/components/shared/AgentView.tsx +48 -51
- package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
- package/.framework/src/components/shared/InviteManager.tsx +113 -52
- package/.framework/src/components/shared/MemberList.tsx +182 -0
- package/.framework/src/components/shared/SchemaFields.tsx +96 -78
- package/.framework/src/components/ui/DataTable.tsx +86 -56
- package/.framework/src/components/ui/Form.tsx +188 -109
- package/.framework/src/components/ui/ItemCard.tsx +86 -58
- package/.framework/src/components/ui/ItemListView.tsx +88 -61
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
- package/.framework/src/components/ui/Modal.tsx +81 -4
- package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
- package/.framework/src/components/ui/accordion.tsx +97 -5
- package/.framework/src/components/ui/alert-dialog.tsx +225 -13
- package/.framework/src/components/ui/alert.tsx +113 -6
- package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
- package/.framework/src/components/ui/avatar.tsx +129 -7
- package/.framework/src/components/ui/badge.tsx +65 -3
- package/.framework/src/components/ui/breadcrumb.tsx +145 -8
- package/.framework/src/components/ui/button-group.tsx +81 -4
- package/.framework/src/components/ui/button.tsx +49 -2
- package/.framework/src/components/ui/calendar.tsx +65 -3
- package/.framework/src/components/ui/card.tsx +145 -8
- package/.framework/src/components/ui/carousel.tsx +129 -7
- package/.framework/src/components/ui/chart.tsx +161 -10
- package/.framework/src/components/ui/checkbox.tsx +49 -2
- package/.framework/src/components/ui/collapsible.tsx +81 -5
- package/.framework/src/components/ui/combobox.tsx +305 -20
- package/.framework/src/components/ui/command.tsx +177 -11
- package/.framework/src/components/ui/context-menu.tsx +273 -17
- package/.framework/src/components/ui/dialog.tsx +209 -27
- package/.framework/src/components/ui/direction.tsx +64 -4
- package/.framework/src/components/ui/drawer.tsx +193 -12
- package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
- package/.framework/src/components/ui/empty.tsx +145 -9
- package/.framework/src/components/ui/field.tsx +209 -14
- package/.framework/src/components/ui/hover-card.tsx +81 -4
- package/.framework/src/components/ui/input-group.tsx +162 -10
- package/.framework/src/components/ui/input-otp.tsx +98 -5
- package/.framework/src/components/ui/input.tsx +49 -2
- package/.framework/src/components/ui/item.tsx +225 -13
- package/.framework/src/components/ui/kbd.tsx +65 -3
- package/.framework/src/components/ui/label.tsx +49 -2
- package/.framework/src/components/ui/menubar.tsx +289 -17
- package/.framework/src/components/ui/native-select.tsx +97 -5
- package/.framework/src/components/ui/navigation-menu.tsx +177 -10
- package/.framework/src/components/ui/pagination.tsx +161 -9
- package/.framework/src/components/ui/popover.tsx +145 -8
- package/.framework/src/components/ui/progress.tsx +49 -2
- package/.framework/src/components/ui/radio-group.tsx +65 -3
- package/.framework/src/components/ui/resizable.tsx +82 -4
- package/.framework/src/components/ui/scroll-area.tsx +65 -3
- package/.framework/src/components/ui/select.tsx +193 -11
- package/.framework/src/components/ui/separator.tsx +49 -2
- package/.framework/src/components/ui/sheet.tsx +193 -11
- package/.framework/src/components/ui/sidebar.tsx +481 -38
- package/.framework/src/components/ui/skeleton.tsx +49 -2
- package/.framework/src/components/ui/slider.tsx +49 -2
- package/.framework/src/components/ui/sonner.tsx +49 -2
- package/.framework/src/components/ui/spinner.tsx +49 -2
- package/.framework/src/components/ui/switch.tsx +49 -2
- package/.framework/src/components/ui/table-primitives.tsx +160 -33
- package/.framework/src/components/ui/table.tsx +161 -9
- package/.framework/src/components/ui/tabs.tsx +113 -6
- package/.framework/src/components/ui/textarea.tsx +49 -2
- package/.framework/src/components/ui/toggle-group.tsx +81 -4
- package/.framework/src/components/ui/toggle.tsx +65 -3
- package/.framework/src/components/ui/tooltip.tsx +97 -5
- package/.framework/src/contexts/AppContext.tsx +129 -45
- package/.framework/src/contexts/AuthContext.tsx +187 -144
- package/.framework/src/hooks/use-mobile.ts +48 -2
- package/.framework/src/hooks/useApi.ts +208 -159
- package/.framework/src/hooks/useAppPath.ts +32 -23
- package/.framework/src/hooks/useApps.ts +51 -20
- package/.framework/src/hooks/useEntityList.ts +32 -78
- package/.framework/src/hooks/useEntityRecord.ts +35 -96
- package/.framework/src/hooks/useForm.ts +32 -92
- package/.framework/src/hooks/useListSchema.ts +49 -78
- package/.framework/src/hooks/useSchemaRecord.ts +114 -105
- package/.framework/src/lib/api.ts +195 -116
- package/.framework/src/lib/supabase.ts +98 -64
- package/.framework/src/lib/utils.ts +287 -151
- package/.framework/src/main.tsx +49 -3
- package/.framework/src/pages/DashboardPage.tsx +52 -29
- package/.framework/src/pages/NotFoundPage.tsx +32 -10
- package/.framework/src/pages/SetupPage.tsx +32 -12
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
- package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
- package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
- package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
- package/.framework/src/pages/admin/AppsPage.tsx +49 -2
- package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
- package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
- package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
- package/.framework/src/pages/admin/LogsPage.tsx +422 -75
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
- package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
- package/.framework/src/pages/admin/RolesPage.tsx +171 -18
- package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
- package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
- package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
- package/.framework/src/pages/admin/TimersPage.tsx +48 -20
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
- package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
- package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
- package/.framework/src/pages/admin/TypesPage.tsx +48 -20
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
- package/.framework/src/pages/auth/LoginPage.tsx +50 -23
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
- package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
- package/.framework/src/types/auth.ts +128 -71
- package/.framework/src/types/types.ts +373 -157
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
- package/docs/README.md +9 -130
- package/netlify.toml +5 -2
- package/package.json +13 -25
- package/scripts/kb-ingest-docs.ts +203 -0
- package/spine.config.json +65 -4
- package/.framework/migrations/001_schema.sql +0 -425
- package/.framework/migrations/002_rls_and_functions.sql +0 -763
- package/.framework/migrations/004_enhancements.sql +0 -43
- package/.framework/migrations/005_auth_user_trigger.sql +0 -105
- package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
- package/.framework/migrations/016_invites.sql +0 -27
- package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
- package/.framework/migrations/018_apps_required_roles.sql +0 -17
- package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
- package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
- package/.framework/migrations/021_app_domains.sql +0 -112
- package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
- package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
- package/.framework/migrations/024_messages_account_id.sql +0 -9
- package/.framework/migrations/025_retype_threads_messages.sql +0 -240
- package/.framework/migrations/026_fix_rls_policies.sql +0 -47
- package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
- package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
- package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
- package/.framework/migrations/030_messages_updated_by.sql +0 -6
- package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
- package/docs/APPS.md +0 -232
- package/docs/ARCHITECTURE.md +0 -246
- package/docs/INSTALL.md +0 -155
- package/docs/design-schema-spec.md +0 -1837
- package/docs/dev-guides/01-create-an-app.md +0 -183
- package/docs/dev-guides/02-create-a-function.md +0 -178
- package/docs/dev-guides/03-create-a-component.md +0 -178
- package/docs/dev-guides/04-webhook-handlers.md +0 -129
- package/docs/dev-guides/05-testing.md +0 -168
- package/docs/dev-guides/README.md +0 -40
- package/docs/npm-packages-plan.md +0 -288
- package/docs/spine-core--api-reference.md +0 -822
|
@@ -1,90 +1,95 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module schema-utils
|
|
3
|
-
* @audience both
|
|
4
|
-
* @layer shared-core
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Schema generation and field-level data transformation for all Spine types.
|
|
8
|
-
*
|
|
9
|
-
* Three public functions form the core contract:
|
|
10
|
-
* - `generateValidationSchema` — derives a runtime validation schema from a
|
|
11
|
-
* `design_schema`, stripping display/permission info and keeping only
|
|
12
|
-
* structural constraints.
|
|
13
|
-
* - `sanitizeFieldData` — coerces and validates a single field value for
|
|
14
|
-
* write (create/update) operations. Throws on invalid data.
|
|
15
|
-
* - `formatFieldData` — converts a stored field value to a human-readable
|
|
16
|
-
* display string for read operations. Never throws.
|
|
17
|
-
* - `transformRecordData` — applies sanitize or format to all fields in a
|
|
18
|
-
* record using a pre-generated ValidationSchema.
|
|
19
|
-
*
|
|
20
|
-
* These are called by `permissions.ts` (`validateFirstSurfaceUpdatePermissions`
|
|
21
|
-
* and `sanitizeFirstSurfaceRecordData`) — do not call them directly from API
|
|
22
|
-
* handlers. Use `PermissionEngine.sanitizeRecordData` / `validateUpdatePermissions`.
|
|
23
|
-
*
|
|
24
|
-
* INVARIANT: all sanitize functions throw on invalid data. Callers must catch
|
|
25
|
-
* errors and convert them to field-level validation error messages.
|
|
26
|
-
* INVARIANT: all format functions return the raw data unchanged if formatting
|
|
27
|
-
* is not applicable (never throw, never return null for non-null input).
|
|
28
|
-
*
|
|
29
|
-
* @seeAlso permissions.ts (primary caller of sanitizeFieldData, formatFieldData)
|
|
30
|
-
* @seeAlso src/types/types.ts (FieldDefinition interface)
|
|
31
|
-
* @seeAlso index.ts (not re-exported — internal to core; use PermissionEngine)
|
|
32
|
-
*/
|
|
33
1
|
|
|
34
|
-
import { FieldDefinition } from '../../src/types/types'
|
|
35
2
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// CIL[BEGIN chunk_id="schemautils_imports_1784020784" type="module_header" identity="imports" parent="none"]
|
|
39
|
+
// CIL[DOC-MACRO purpose="Import field definition type for schema utilities"]
|
|
40
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Import FieldDefinition interface from types"]
|
|
41
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/migrations/025_retype_threads_messages.sql\",\"\\\"]"]
|
|
42
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="FieldDefinition type" errors="none" side_effects="none"]
|
|
43
|
+
// CIL[DOC-MICRO logic_summary="Import type definition for field structure" notable_decisions="[]"]
|
|
44
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
45
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
46
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
47
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/migrations/025_retype_threads_messages.sql, \."]
|
|
48
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
49
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
50
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
51
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
52
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
53
|
+
import { FieldDefinition } from '../../src/types/types'
|
|
54
|
+
// CIL[END chunk_id="schemautils_imports_1784020784"]
|
|
55
|
+
// CIL[BEGIN chunk_id="schemautils_validationinterface_1784020784" type="interface" identity="ValidationSchema" parent="none"]
|
|
56
|
+
// CIL[DOC-MACRO purpose="Define validation schema interface for field validation"]
|
|
57
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide structure for validation rules per field"]
|
|
58
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[\".framework/src/components/layout/Sidebar.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
|
|
59
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ValidationSchema interface" errors="none" side_effects="none"]
|
|
60
|
+
// CIL[DOC-MICRO logic_summary="Interface with fields containing data_type and validation rules" notable_decisions="[]"]
|
|
61
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
62
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
63
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: .framework/src/components/layout/Sidebar.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, \."]
|
|
64
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
65
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
66
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
67
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
68
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
51
69
|
export interface ValidationSchema {
|
|
52
70
|
fields: Record<string, {
|
|
53
71
|
data_type: string
|
|
54
72
|
required?: boolean
|
|
55
|
-
[key: string]: any
|
|
73
|
+
[key: string]: any
|
|
56
74
|
}>
|
|
57
75
|
}
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
* @inputSpec designSchema.fields[x].data_type: string — required in every field
|
|
76
|
-
* @outputSpec ValidationSchema.fields: Record<string, { data_type, required, ...constraints }>
|
|
77
|
-
* @sideEffects none
|
|
78
|
-
* @calledBy permissions.ts (validateFirstSurfaceUpdatePermissions), any caller
|
|
79
|
-
* needing a validation schema without the full design_schema overhead
|
|
80
|
-
* @testUnit tests/unit/schema-utils.test.ts — 'generateValidationSchema' describe block
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```ts
|
|
84
|
-
* const schema = generateValidationSchema(record.design_schema)
|
|
85
|
-
* const cleaned = transformRecordData(record.data, schema, 'sanitize')
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
76
|
+
// CIL[END chunk_id="schemautils_validationinterface_1784020784"]
|
|
77
|
+
// CIL[BEGIN chunk_id="schemautils_generatevalidationschema_1784020784" type="function" identity="generateValidationSchema" parent="none"]
|
|
78
|
+
// CIL[DOC-LEARNING topic="runtime-type:generic/validation_generation" content="generateValidationSchema builds a Zod-compatible validation schema from design_schema.fields. It uses data_type, required, validation, options, and reference fields to produce row-level and data-level validators."]
|
|
79
|
+
// CIL[DOC-NOTE type="design_schema_caveat" content="Unsupported data_types or validation keys are ignored. Reference fields need reference_kind and reference_type or validation will not enforce foreign keys."]
|
|
80
|
+
// CIL[DOC-MACRO purpose="Generate validation schema from design schema"]
|
|
81
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert design schema to validation rules"]
|
|
82
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
|
|
83
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ValidationSchema" errors="none" side_effects="none"]
|
|
84
|
+
// CIL[DOC-MICRO logic_summary="Extracts field definitions and builds validation schema" notable_decisions="[]"]
|
|
85
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
86
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
87
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/src/pages/admin/RolesPage.tsx, \."]
|
|
88
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
89
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
90
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
91
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
92
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
88
93
|
export function generateValidationSchema(designSchema: any): ValidationSchema {
|
|
89
94
|
const validationSchema: ValidationSchema = {
|
|
90
95
|
fields: {}
|
|
@@ -97,23 +102,19 @@ export function generateValidationSchema(designSchema: any): ValidationSchema {
|
|
|
97
102
|
for (const [fieldName, fieldDef] of Object.entries(designSchema.fields)) {
|
|
98
103
|
const field = fieldDef as FieldDefinition
|
|
99
104
|
|
|
100
|
-
// Extract only structural validation properties exactly as declared
|
|
101
105
|
const validationField: any = {
|
|
102
106
|
data_type: field.data_type,
|
|
103
107
|
required: field.required
|
|
104
108
|
}
|
|
105
109
|
|
|
106
|
-
// Add explicit validation constraints exactly as declared
|
|
107
110
|
if (field.validation) {
|
|
108
111
|
Object.assign(validationField, field.validation)
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
// Add type-specific constraint properties (moved out of validation for clarity)
|
|
112
114
|
if (field.options) {
|
|
113
115
|
validationField.options = field.options
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
// Add reference properties if they exist
|
|
117
118
|
if (field.data_type === 'reference' && field.validation) {
|
|
118
119
|
if (field.validation.reference_kind) validationField.reference_kind = field.validation.reference_kind
|
|
119
120
|
if (field.validation.reference_type) validationField.reference_type = field.validation.reference_type
|
|
@@ -124,41 +125,21 @@ export function generateValidationSchema(designSchema: any): ValidationSchema {
|
|
|
124
125
|
|
|
125
126
|
return validationSchema
|
|
126
127
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
* @returns Sanitized value in the correct type for storage
|
|
143
|
-
* @throws Error — descriptive message naming the field constraint violated
|
|
144
|
-
* @inputSpec data: any — null and undefined are returned as-is without sanitization
|
|
145
|
-
* @inputSpec data_type: string — one of the 21 supported type keys (see switch below)
|
|
146
|
-
* @inputSpec validation: object | undefined — type-specific constraints
|
|
147
|
-
* @outputSpec any — coerced value matching the data_type storage format
|
|
148
|
-
* @sideEffects none
|
|
149
|
-
* @calledBy permissions.ts (validateFirstSurfaceUpdatePermissions, per-field loop)
|
|
150
|
-
* @calls sanitizeText | sanitizeTextarea | sanitizeEmail | sanitizeNumber | etc.
|
|
151
|
-
* @testUnit tests/unit/schema-utils.test.ts — 'sanitizeFieldData' describe block
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
* ```ts
|
|
155
|
-
* const clean = sanitizeFieldData('hello@EXAMPLE.COM', 'email')
|
|
156
|
-
* // → 'hello@example.com'
|
|
157
|
-
*
|
|
158
|
-
* sanitizeFieldData('not-a-url', 'url')
|
|
159
|
-
* // throws Error('Invalid URL format')
|
|
160
|
-
* ```
|
|
161
|
-
*/
|
|
128
|
+
// CIL[END chunk_id="schemautils_generatevalidationschema_1784020784"]
|
|
129
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizefielddata_1784020784" type="function" identity="sanitizeFieldData" parent="none"]
|
|
130
|
+
// CIL[DOC-MACRO purpose="Dispatch sanitization based on field data type"]
|
|
131
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Route data to appropriate sanitizer function"]
|
|
132
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[\".framework/migrations/025_retype_threads_messages.sql\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\"\\\"]"]
|
|
133
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="sanitized data" errors="validation errors" side_effects="none"]
|
|
134
|
+
// CIL[DOC-MICRO logic_summary="Switch statement routes to type-specific sanitizers" notable_decisions="[]"]
|
|
135
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
136
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
137
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/025_retype_threads_messages.sql, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/components/ui/dialog.tsx, \."]
|
|
138
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
139
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
140
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
141
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
142
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
162
143
|
export function sanitizeFieldData(
|
|
163
144
|
data: any,
|
|
164
145
|
data_type: string,
|
|
@@ -217,40 +198,21 @@ export function sanitizeFieldData(
|
|
|
217
198
|
return data
|
|
218
199
|
}
|
|
219
200
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
* @throws never
|
|
236
|
-
* @inputSpec data: any — null and undefined are returned as-is
|
|
237
|
-
* @inputSpec data_type: string — one of 21 supported keys; unknown → pass-through
|
|
238
|
-
* @inputSpec context: object | undefined — type-specific display hints
|
|
239
|
-
* @outputSpec any — display-ready value; string for most types, raw data for pass-through
|
|
240
|
-
* @sideEffects none
|
|
241
|
-
* @calledBy permissions.ts (sanitizeFirstSurfaceRecordData, per-field loop)
|
|
242
|
-
* @calls formatJson | formatDate | formatDatetime | formatCurrency | etc.
|
|
243
|
-
* @testUnit tests/unit/schema-utils.test.ts — 'formatFieldData' describe block
|
|
244
|
-
*
|
|
245
|
-
* @example
|
|
246
|
-
* ```ts
|
|
247
|
-
* formatFieldData('2024-01-15', 'date')
|
|
248
|
-
* // → 'January 15, 2024'
|
|
249
|
-
*
|
|
250
|
-
* formatFieldData(1234.5, 'currency', { currency_code: 'USD' })
|
|
251
|
-
* // → '$1,234.50'
|
|
252
|
-
* ```
|
|
253
|
-
*/
|
|
201
|
+
// CIL[END chunk_id="schemautils_sanitizefielddata_1784020784"]
|
|
202
|
+
// CIL[BEGIN chunk_id="schemautils_formatfielddata_1784020784" type="function" identity="formatFieldData" parent="none"]
|
|
203
|
+
// CIL[DOC-MACRO purpose="Dispatch formatting based on field data type"]
|
|
204
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Route data to appropriate formatter function"]
|
|
205
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[\".framework/migrations/025_retype_threads_messages.sql\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/src/components/ui/dialog.tsx\",\"\\\"]"]
|
|
206
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted data" errors="none" side_effects="none"]
|
|
207
|
+
// CIL[DOC-MICRO logic_summary="Switch statement routes to type-specific formatters" notable_decisions="[]"]
|
|
208
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
209
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
210
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/025_retype_threads_messages.sql, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/src/components/ui/dialog.tsx, \."]
|
|
211
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
212
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
213
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
214
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
215
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
254
216
|
export function formatFieldData(
|
|
255
217
|
data: any,
|
|
256
218
|
data_type: string,
|
|
@@ -285,37 +247,21 @@ export function formatFieldData(
|
|
|
285
247
|
return data
|
|
286
248
|
}
|
|
287
249
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
* @inputSpec data: Record<string, any> — flat field map
|
|
304
|
-
* @inputSpec validationSchema: ValidationSchema — from generateValidationSchema
|
|
305
|
-
* @inputSpec operation: 'sanitize' | 'format'
|
|
306
|
-
* @outputSpec Record<string, any> — same keys, transformed values
|
|
307
|
-
* @sideEffects none
|
|
308
|
-
* @calledBy Custom code in v2-custom/ that needs bulk field transformation
|
|
309
|
-
* @calls sanitizeFieldData | formatFieldData (per field)
|
|
310
|
-
* @testUnit tests/unit/schema-utils.test.ts — 'transformRecordData' describe block
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* ```ts
|
|
314
|
-
* const schema = generateValidationSchema(type.design_schema)
|
|
315
|
-
* const sanitized = transformRecordData(body.data, schema, 'sanitize')
|
|
316
|
-
* const formatted = transformRecordData(record.data, schema, 'format', ctx)
|
|
317
|
-
* ```
|
|
318
|
-
*/
|
|
250
|
+
// CIL[END chunk_id="schemautils_formatfielddata_1784020784"]
|
|
251
|
+
// CIL[BEGIN chunk_id="schemautils_transformrecorddata_1784020784" type="function" identity="transformRecordData" parent="none"]
|
|
252
|
+
// CIL[DOC-MACRO purpose="Transform record data using validation schema"]
|
|
253
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Apply sanitization or formatting to all record fields"]
|
|
254
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
255
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="transformed data" errors="none" side_effects="none"]
|
|
256
|
+
// CIL[DOC-MICRO logic_summary="Iterates through fields and applies appropriate transformation" notable_decisions="[]"]
|
|
257
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
258
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
259
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
260
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
261
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
262
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
263
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
264
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
319
265
|
export function transformRecordData(
|
|
320
266
|
data: Record<string, any>,
|
|
321
267
|
validationSchema: ValidationSchema,
|
|
@@ -328,7 +274,6 @@ export function transformRecordData(
|
|
|
328
274
|
const fieldValidation = validationSchema.fields[fieldName]
|
|
329
275
|
|
|
330
276
|
if (!fieldValidation) {
|
|
331
|
-
// No validation schema for this field, pass through as-is
|
|
332
277
|
transformed[fieldName] = fieldValue
|
|
333
278
|
continue
|
|
334
279
|
}
|
|
@@ -350,22 +295,26 @@ export function transformRecordData(
|
|
|
350
295
|
|
|
351
296
|
return transformed
|
|
352
297
|
}
|
|
353
|
-
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
298
|
+
// CIL[END chunk_id="schemautils_transformrecorddata_1784020784"]
|
|
299
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizetext_1784020784" type="function" identity="sanitizeText" parent="none"]
|
|
300
|
+
// CIL[DOC-MACRO purpose="Sanitize text field data with HTML encoding"]
|
|
301
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Clean text and apply validation rules"]
|
|
302
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
303
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="sanitized string" errors="validation errors" side_effects="none"]
|
|
304
|
+
// CIL[DOC-MICRO logic_summary="Removes control chars, HTML encodes, validates length/pattern" notable_decisions="[]"]
|
|
305
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
306
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
307
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
308
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
309
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
310
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
311
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
312
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
362
313
|
function sanitizeText(data: any, validation?: any): string {
|
|
363
314
|
let text = String(data).trim()
|
|
364
315
|
|
|
365
|
-
// Remove control characters except newlines and tabs
|
|
366
316
|
text = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')
|
|
367
317
|
|
|
368
|
-
// Escape HTML entities
|
|
369
318
|
text = text
|
|
370
319
|
.replace(/&/g, '&')
|
|
371
320
|
.replace(/</g, '<')
|
|
@@ -373,7 +322,6 @@ function sanitizeText(data: any, validation?: any): string {
|
|
|
373
322
|
.replace(/"/g, '"')
|
|
374
323
|
.replace(/'/g, ''')
|
|
375
324
|
|
|
376
|
-
// Apply length constraints
|
|
377
325
|
if (validation?.minLength && text.length < validation.minLength) {
|
|
378
326
|
throw new Error(`Text must be at least ${validation.minLength} characters`)
|
|
379
327
|
}
|
|
@@ -381,7 +329,6 @@ function sanitizeText(data: any, validation?: any): string {
|
|
|
381
329
|
text = text.substring(0, validation.maxLength)
|
|
382
330
|
}
|
|
383
331
|
|
|
384
|
-
// Apply pattern validation
|
|
385
332
|
if (validation?.pattern) {
|
|
386
333
|
const regex = new RegExp(validation.pattern)
|
|
387
334
|
if (!regex.test(text)) {
|
|
@@ -391,19 +338,26 @@ function sanitizeText(data: any, validation?: any): string {
|
|
|
391
338
|
|
|
392
339
|
return text
|
|
393
340
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
341
|
+
// CIL[END chunk_id="schemautils_sanitizetext_1784020784"]
|
|
342
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizetextarea_1784020784" type="function" identity="sanitizeTextarea" parent="none"]
|
|
343
|
+
// CIL[DOC-MACRO purpose="Sanitize textarea field data"]
|
|
344
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Clean textarea content and validate length"]
|
|
345
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
346
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="sanitized string" errors="length validation errors" side_effects="none"]
|
|
347
|
+
// CIL[DOC-MICRO logic_summary="Removes control chars, HTML encodes, checks length limits" notable_decisions="[]"]
|
|
348
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
349
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
350
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
351
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
352
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
353
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
354
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
355
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
400
356
|
function sanitizeTextarea(data: any, validation?: any): string {
|
|
401
357
|
let text = String(data).trim()
|
|
402
358
|
|
|
403
|
-
// Remove control characters except newlines and tabs
|
|
404
359
|
text = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')
|
|
405
360
|
|
|
406
|
-
// Escape HTML entities but preserve line breaks
|
|
407
361
|
text = text
|
|
408
362
|
.replace(/&/g, '&')
|
|
409
363
|
.replace(/</g, '<')
|
|
@@ -411,7 +365,6 @@ function sanitizeTextarea(data: any, validation?: any): string {
|
|
|
411
365
|
.replace(/"/g, '"')
|
|
412
366
|
.replace(/'/g, ''')
|
|
413
367
|
|
|
414
|
-
// Apply length constraints
|
|
415
368
|
if (validation?.minLength && text.length < validation.minLength) {
|
|
416
369
|
throw new Error(`Text must be at least ${validation.minLength} characters`)
|
|
417
370
|
}
|
|
@@ -421,17 +374,24 @@ function sanitizeTextarea(data: any, validation?: any): string {
|
|
|
421
374
|
|
|
422
375
|
return text
|
|
423
376
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
377
|
+
// CIL[END chunk_id="schemautils_sanitizetextarea_1784020784"]
|
|
378
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizerichtext_1784020784" type="function" identity="sanitizeRichText" parent="none"]
|
|
379
|
+
// CIL[DOC-MACRO purpose="Sanitize rich text HTML content"]
|
|
380
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Filter HTML tags and remove dangerous content"]
|
|
381
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
382
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="sanitized HTML" errors="length validation errors" side_effects="none"]
|
|
383
|
+
// CIL[DOC-MICRO logic_summary="Allows safe tags, removes scripts, strips event handlers" notable_decisions="[]"]
|
|
384
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
385
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
386
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
387
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
388
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
389
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
390
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
391
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
431
392
|
function sanitizeRichText(data: any, validation?: any): string {
|
|
432
393
|
let html = String(data).trim()
|
|
433
394
|
|
|
434
|
-
// Basic HTML sanitization - allow only safe tags
|
|
435
395
|
const allowedTags = ['p', 'br', 'strong', 'em', 'u', 'ol', 'ul', 'li', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']
|
|
436
396
|
const tagRegex = /<\/?([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>/g
|
|
437
397
|
|
|
@@ -442,11 +402,9 @@ function sanitizeRichText(data: any, validation?: any): string {
|
|
|
442
402
|
return ''
|
|
443
403
|
})
|
|
444
404
|
|
|
445
|
-
// Remove script tags and on* attributes
|
|
446
405
|
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
|
|
447
406
|
html = html.replace(/on\w+\s*=/gi, '')
|
|
448
407
|
|
|
449
|
-
// Apply length constraints
|
|
450
408
|
if (validation?.minLength && html.length < validation.minLength) {
|
|
451
409
|
throw new Error(`Content must be at least ${validation.minLength} characters`)
|
|
452
410
|
}
|
|
@@ -456,15 +414,24 @@ function sanitizeRichText(data: any, validation?: any): string {
|
|
|
456
414
|
|
|
457
415
|
return html
|
|
458
416
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
417
|
+
// CIL[END chunk_id="schemautils_sanitizerichtext_1784020784"]
|
|
418
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeemail_1784020784" type="function" identity="sanitizeEmail" parent="none"]
|
|
419
|
+
// CIL[DOC-MACRO purpose="Validate and sanitize email addresses"]
|
|
420
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure email format is valid"]
|
|
421
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
422
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="normalized email" errors="invalid format error" side_effects="none"]
|
|
423
|
+
// CIL[DOC-MICRO logic_summary="Lowercases, trims, validates with regex pattern" notable_decisions="[]"]
|
|
424
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
425
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
426
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
427
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
428
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
429
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
430
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
431
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
464
432
|
function sanitizeEmail(data: any, validation?: any): string {
|
|
465
433
|
let email = String(data).toLowerCase().trim()
|
|
466
434
|
|
|
467
|
-
// Basic email validation
|
|
468
435
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
469
436
|
if (!emailRegex.test(email)) {
|
|
470
437
|
throw new Error('Invalid email format')
|
|
@@ -472,18 +439,26 @@ function sanitizeEmail(data: any, validation?: any): string {
|
|
|
472
439
|
|
|
473
440
|
return email
|
|
474
441
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
442
|
+
// CIL[END chunk_id="schemautils_sanitizeemail_1784020784"]
|
|
443
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizephone_1784020784" type="function" identity="sanitizePhone" parent="none"]
|
|
444
|
+
// CIL[DOC-MACRO purpose="Sanitize phone number format"]
|
|
445
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Clean and validate phone numbers"]
|
|
446
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
447
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="cleaned phone" errors="format validation errors" side_effects="none"]
|
|
448
|
+
// CIL[DOC-MICRO logic_summary="Removes non-digits, validates against pattern if provided" notable_decisions="[]"]
|
|
449
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
450
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
451
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
452
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
453
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
454
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
455
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
456
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
480
457
|
function sanitizePhone(data: any, validation?: any): string {
|
|
481
458
|
let phone = String(data).trim()
|
|
482
459
|
|
|
483
|
-
// Remove all non-digit characters except +
|
|
484
460
|
phone = phone.replace(/[^\d+]/g, '')
|
|
485
461
|
|
|
486
|
-
// Apply pattern validation if specified
|
|
487
462
|
if (validation?.pattern) {
|
|
488
463
|
const regex = new RegExp(validation.pattern)
|
|
489
464
|
if (!regex.test(phone)) {
|
|
@@ -493,18 +468,26 @@ function sanitizePhone(data: any, validation?: any): string {
|
|
|
493
468
|
|
|
494
469
|
return phone
|
|
495
470
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
471
|
+
// CIL[END chunk_id="schemautils_sanitizephone_1784020784"]
|
|
472
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeurl_1784020784" type="function" identity="sanitizeUrl" parent="none"]
|
|
473
|
+
// CIL[DOC-MACRO purpose="Validate and sanitize URLs"]
|
|
474
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure URL format and protocol are valid"]
|
|
475
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
476
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="normalized URL" errors="invalid URL error" side_effects="none"]
|
|
477
|
+
// CIL[DOC-MICRO logic_summary="Validates URL format, restricts to HTTP/HTTPS protocols" notable_decisions="[]"]
|
|
478
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
479
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
480
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
481
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
482
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
483
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
484
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
485
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
501
486
|
function sanitizeUrl(data: any, validation?: any): string {
|
|
502
487
|
let url = String(data).trim()
|
|
503
488
|
|
|
504
|
-
// Basic URL validation
|
|
505
489
|
try {
|
|
506
490
|
const urlObj = new URL(url)
|
|
507
|
-
// Only allow http/https protocols
|
|
508
491
|
if (!['http:', 'https:'].includes(urlObj.protocol)) {
|
|
509
492
|
throw new Error('Only HTTP and HTTPS URLs are allowed')
|
|
510
493
|
}
|
|
@@ -513,12 +496,21 @@ function sanitizeUrl(data: any, validation?: any): string {
|
|
|
513
496
|
throw new Error('Invalid URL format')
|
|
514
497
|
}
|
|
515
498
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
499
|
+
// CIL[END chunk_id="schemautils_sanitizeurl_1784020784"]
|
|
500
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizenumber_1784020784" type="function" identity="sanitizeNumber" parent="none"]
|
|
501
|
+
// CIL[DOC-MACRO purpose="Validate and sanitize numeric values"]
|
|
502
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure number validity and range constraints"]
|
|
503
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
504
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated number" errors="range/validation errors" side_effects="none"]
|
|
505
|
+
// CIL[DOC-MICRO logic_summary="Validates NaN, checks min/max, applies step rounding" notable_decisions="[]"]
|
|
506
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
507
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
508
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
509
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
510
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
511
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
512
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
513
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
522
514
|
function sanitizeNumber(data: any, validation?: any): number {
|
|
523
515
|
let num = Number(data)
|
|
524
516
|
|
|
@@ -526,7 +518,6 @@ function sanitizeNumber(data: any, validation?: any): number {
|
|
|
526
518
|
throw new Error('Invalid number')
|
|
527
519
|
}
|
|
528
520
|
|
|
529
|
-
// Apply min/max constraints
|
|
530
521
|
if (validation?.min !== undefined && num < validation.min) {
|
|
531
522
|
throw new Error(`Number must be at least ${validation.min}`)
|
|
532
523
|
}
|
|
@@ -534,21 +525,30 @@ function sanitizeNumber(data: any, validation?: any): number {
|
|
|
534
525
|
throw new Error(`Number must be at most ${validation.max}`)
|
|
535
526
|
}
|
|
536
527
|
|
|
537
|
-
// Apply step constraint
|
|
538
528
|
if (validation?.step) {
|
|
539
529
|
const remainder = num % validation.step
|
|
540
530
|
if (remainder !== 0) {
|
|
541
|
-
num = num - remainder
|
|
531
|
+
num = num - remainder
|
|
542
532
|
}
|
|
543
533
|
}
|
|
544
534
|
|
|
545
535
|
return num
|
|
546
536
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
537
|
+
// CIL[END chunk_id="schemautils_sanitizenumber_1784020784"]
|
|
538
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeurrency_1784020784" type="function" identity="sanitizeCurrency" parent="none"]
|
|
539
|
+
// CIL[DOC-MACRO purpose="Sanitize currency amounts with rounding"]
|
|
540
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Validate and round currency values"]
|
|
541
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
542
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="rounded currency" errors="range/validation errors" side_effects="none"]
|
|
543
|
+
// CIL[DOC-MICRO logic_summary="Rounds to 2 decimal places, validates range constraints" notable_decisions="[]"]
|
|
544
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
545
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
546
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
547
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
548
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
549
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
550
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
551
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
552
552
|
function sanitizeCurrency(data: any, validation?: any): number {
|
|
553
553
|
let num = Number(data)
|
|
554
554
|
|
|
@@ -556,10 +556,8 @@ function sanitizeCurrency(data: any, validation?: any): number {
|
|
|
556
556
|
throw new Error('Invalid currency amount')
|
|
557
557
|
}
|
|
558
558
|
|
|
559
|
-
// Round to 2 decimal places for currency
|
|
560
559
|
num = Math.round(num * 100) / 100
|
|
561
560
|
|
|
562
|
-
// Apply min/max constraints
|
|
563
561
|
if (validation?.min !== undefined && num < validation.min) {
|
|
564
562
|
throw new Error(`Amount must be at least ${validation.min}`)
|
|
565
563
|
}
|
|
@@ -569,30 +567,49 @@ function sanitizeCurrency(data: any, validation?: any): number {
|
|
|
569
567
|
|
|
570
568
|
return num
|
|
571
569
|
}
|
|
572
|
-
|
|
573
|
-
|
|
570
|
+
// CIL[END chunk_id="schemautils_sanitizeurrency_1784020784"]
|
|
571
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizerange_1784020784" type="function" identity="sanitizeRange" parent="none"]
|
|
572
|
+
// CIL[DOC-MACRO purpose="Sanitize range values"]
|
|
573
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Delegate range sanitization to number sanitizer"]
|
|
574
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
575
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="sanitized number" errors="number validation errors" side_effects="none"]
|
|
576
|
+
// CIL[DOC-MICRO logic_summary="Simple wrapper around sanitizeNumber function" notable_decisions="[]"]
|
|
577
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
578
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
579
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
580
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
581
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
582
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
583
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
584
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
574
585
|
function sanitizeRange(data: any, validation?: any): number {
|
|
575
586
|
return sanitizeNumber(data, validation)
|
|
576
587
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
588
|
+
// CIL[END chunk_id="schemautils_sanitizerange_1784020784"]
|
|
589
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizedate_1784020784" type="function" identity="sanitizeDate" parent="none"]
|
|
590
|
+
// CIL[DOC-MACRO purpose="Validate and format date strings"]
|
|
591
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure valid date format and constraints"]
|
|
592
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
593
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ISO date string" errors="date validation errors" side_effects="none"]
|
|
594
|
+
// CIL[DOC-MICRO logic_summary="Parses date, validates range, returns ISO format" notable_decisions="[]"]
|
|
595
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
596
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
597
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
598
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
599
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
600
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
601
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
602
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
583
603
|
function sanitizeDate(data: any, validation?: any): string {
|
|
584
604
|
let dateStr = String(data).trim()
|
|
585
605
|
|
|
586
|
-
// Try to parse as ISO date
|
|
587
606
|
const date = new Date(dateStr)
|
|
588
607
|
if (isNaN(date.getTime())) {
|
|
589
608
|
throw new Error('Invalid date format')
|
|
590
609
|
}
|
|
591
610
|
|
|
592
|
-
// Return as ISO date string
|
|
593
611
|
const isoDate = date.toISOString().split('T')[0]
|
|
594
612
|
|
|
595
|
-
// Apply min/max constraints
|
|
596
613
|
if (validation?.min) {
|
|
597
614
|
const minDate = new Date(validation.min)
|
|
598
615
|
if (date < minDate) {
|
|
@@ -608,25 +625,31 @@ function sanitizeDate(data: any, validation?: any): string {
|
|
|
608
625
|
|
|
609
626
|
return isoDate
|
|
610
627
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
628
|
+
// CIL[END chunk_id="schemautils_sanitizedate_1784020784"]
|
|
629
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizedatetime_1784020784" type="function" identity="sanitizeDatetime" parent="none"]
|
|
630
|
+
// CIL[DOC-MACRO purpose="Validate and format datetime strings"]
|
|
631
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure valid datetime format and constraints"]
|
|
632
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
633
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="ISO datetime string" errors="datetime validation errors" side_effects="none"]
|
|
634
|
+
// CIL[DOC-MICRO logic_summary="Parses datetime, validates range, returns ISO format" notable_decisions="[]"]
|
|
635
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
636
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
637
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
638
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
639
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
640
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
641
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
642
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
617
643
|
function sanitizeDatetime(data: any, validation?: any): string {
|
|
618
644
|
let dateStr = String(data).trim()
|
|
619
645
|
|
|
620
|
-
// Try to parse as ISO datetime
|
|
621
646
|
const date = new Date(dateStr)
|
|
622
647
|
if (isNaN(date.getTime())) {
|
|
623
648
|
throw new Error('Invalid datetime format')
|
|
624
649
|
}
|
|
625
650
|
|
|
626
|
-
// Return as ISO datetime string
|
|
627
651
|
const isoDatetime = date.toISOString()
|
|
628
652
|
|
|
629
|
-
// Apply min/max constraints
|
|
630
653
|
if (validation?.min) {
|
|
631
654
|
const minDate = new Date(validation.min)
|
|
632
655
|
if (date < minDate) {
|
|
@@ -642,12 +665,21 @@ function sanitizeDatetime(data: any, validation?: any): string {
|
|
|
642
665
|
|
|
643
666
|
return isoDatetime
|
|
644
667
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
668
|
+
// CIL[END chunk_id="schemautils_sanitizedatetime_1784020784"]
|
|
669
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeboolean_1784020784" type="function" identity="sanitizeBoolean" parent="none"]
|
|
670
|
+
// CIL[DOC-MACRO purpose="Convert and sanitize boolean values"]
|
|
671
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Normalize various boolean representations"]
|
|
672
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
673
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="boolean value" errors="invalid boolean error" side_effects="none"]
|
|
674
|
+
// CIL[DOC-MICRO logic_summary="Handles boolean, string, number representations" notable_decisions="[]"]
|
|
675
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
676
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
677
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
678
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
679
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
680
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
681
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
682
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
651
683
|
function sanitizeBoolean(data: any, validation?: any): boolean {
|
|
652
684
|
if (typeof data === 'boolean') {
|
|
653
685
|
return data
|
|
@@ -662,22 +694,43 @@ function sanitizeBoolean(data: any, validation?: any): boolean {
|
|
|
662
694
|
|
|
663
695
|
throw new Error('Invalid boolean value')
|
|
664
696
|
}
|
|
665
|
-
|
|
666
|
-
|
|
697
|
+
// CIL[END chunk_id="schemautils_sanitizeboolean_1784020784"]
|
|
698
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizecheckbox_1784020784" type="function" identity="sanitizeCheckbox" parent="none"]
|
|
699
|
+
// CIL[DOC-MACRO purpose="Sanitize checkbox boolean values"]
|
|
700
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Delegate checkbox sanitization to boolean sanitizer"]
|
|
701
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
702
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="boolean value" errors="boolean validation errors" side_effects="none"]
|
|
703
|
+
// CIL[DOC-MICRO logic_summary="Simple wrapper around sanitizeBoolean function" notable_decisions="[]"]
|
|
704
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
705
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
706
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
707
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
708
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
709
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
710
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
711
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
667
712
|
function sanitizeCheckbox(data: any, validation?: any): boolean {
|
|
668
713
|
return sanitizeBoolean(data, validation)
|
|
669
714
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
715
|
+
// CIL[END chunk_id="schemautils_sanitizecheckbox_1784020784"]
|
|
716
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeselect_1784020784" type="function" identity="sanitizeSelect" parent="none"]
|
|
717
|
+
// CIL[DOC-MACRO purpose="Validate select field options"]
|
|
718
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure selected value is in allowed options"]
|
|
719
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
720
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated option" errors="invalid option error" side_effects="none"]
|
|
721
|
+
// CIL[DOC-MICRO logic_summary="Trims value, checks against allowed options array" notable_decisions="[]"]
|
|
722
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
723
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
724
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
725
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
726
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
727
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
728
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
729
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
675
730
|
function sanitizeSelect(data: any, validation?: any): string {
|
|
676
731
|
let value = String(data).trim()
|
|
677
732
|
|
|
678
|
-
// Validate against allowed options
|
|
679
733
|
if (validation?.options) {
|
|
680
|
-
// Options are now just an array of strings
|
|
681
734
|
const allowedValues = Array.isArray(validation.options) ? validation.options : []
|
|
682
735
|
if (!allowedValues.includes(value)) {
|
|
683
736
|
throw new Error('Invalid option selected')
|
|
@@ -686,12 +739,21 @@ function sanitizeSelect(data: any, validation?: any): string {
|
|
|
686
739
|
|
|
687
740
|
return value
|
|
688
741
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
742
|
+
// CIL[END chunk_id="schemautils_sanitizeselect_1784020784"]
|
|
743
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizemultiselect_1784020784" type="function" identity="sanitizeMultiselect" parent="none"]
|
|
744
|
+
// CIL[DOC-MACRO purpose="Validate multiselect array values"]
|
|
745
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Handle array or comma-separated multiselect data"]
|
|
746
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
747
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated array" errors="invalid option errors" side_effects="none"]
|
|
748
|
+
// CIL[DOC-MICRO logic_summary="Converts to array, removes duplicates, validates options" notable_decisions="[]"]
|
|
749
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
750
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
751
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
752
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
753
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
754
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
755
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
756
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
695
757
|
function sanitizeMultiselect(data: any, validation?: any): string[] {
|
|
696
758
|
let values: string[]
|
|
697
759
|
|
|
@@ -703,12 +765,9 @@ function sanitizeMultiselect(data: any, validation?: any): string[] {
|
|
|
703
765
|
throw new Error('Multiselect must be an array or comma-separated string')
|
|
704
766
|
}
|
|
705
767
|
|
|
706
|
-
// Remove duplicates
|
|
707
768
|
values = [...new Set(values)]
|
|
708
769
|
|
|
709
|
-
// Validate against allowed options
|
|
710
770
|
if (validation?.options) {
|
|
711
|
-
// Options are now just an array of strings
|
|
712
771
|
const allowedValues = Array.isArray(validation.options) ? validation.options : []
|
|
713
772
|
for (const value of values) {
|
|
714
773
|
if (!allowedValues.includes(value)) {
|
|
@@ -717,89 +776,129 @@ function sanitizeMultiselect(data: any, validation?: any): string[] {
|
|
|
717
776
|
}
|
|
718
777
|
}
|
|
719
778
|
|
|
720
|
-
// Apply max selection count
|
|
721
779
|
if (validation?.max && values.length > validation.max) {
|
|
722
780
|
values = values.slice(0, validation.max)
|
|
723
781
|
}
|
|
724
782
|
|
|
725
783
|
return values
|
|
726
784
|
}
|
|
727
|
-
|
|
728
|
-
|
|
785
|
+
// CIL[END chunk_id="schemautils_sanitizemultiselect_1784020784"]
|
|
786
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeradio_1784020784" type="function" identity="sanitizeRadio" parent="none"]
|
|
787
|
+
// CIL[DOC-MACRO purpose="Validate radio button selections"]
|
|
788
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Delegate radio sanitization to select sanitizer"]
|
|
789
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
790
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated option" errors="invalid option error" side_effects="none"]
|
|
791
|
+
// CIL[DOC-MICRO logic_summary="Simple wrapper around sanitizeSelect function" notable_decisions="[]"]
|
|
792
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
793
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
794
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
795
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
796
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
797
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
798
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
799
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
729
800
|
function sanitizeRadio(data: any, validation?: any): string {
|
|
730
801
|
return sanitizeSelect(data, validation)
|
|
731
802
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
803
|
+
// CIL[END chunk_id="schemautils_sanitizeradio_1784020784"]
|
|
804
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeolor_1784020784" type="function" identity="sanitizeColor" parent="none"]
|
|
805
|
+
// CIL[DOC-MACRO purpose="Validate and format hex color codes"]
|
|
806
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure proper hex color format"]
|
|
807
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
808
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="normalized hex color" errors="invalid color format error" side_effects="none"]
|
|
809
|
+
// CIL[DOC-MICRO logic_summary="Validates hex format, converts 3-digit to 6-digit, uppercases" notable_decisions="[]"]
|
|
810
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
811
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
812
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
813
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
814
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
815
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
816
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
817
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
737
818
|
function sanitizeColor(data: any, validation?: any): string {
|
|
738
819
|
let color = String(data).trim()
|
|
739
820
|
|
|
740
|
-
// Validate hex color format
|
|
741
821
|
const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
|
|
742
822
|
if (!hexRegex.test(color)) {
|
|
743
823
|
throw new Error('Invalid color format. Use #RRGGBB or #RGB format')
|
|
744
824
|
}
|
|
745
825
|
|
|
746
|
-
// Normalize to 6-digit hex
|
|
747
826
|
if (color.length === 4) {
|
|
748
827
|
color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3]
|
|
749
828
|
}
|
|
750
829
|
|
|
751
830
|
return color.toUpperCase()
|
|
752
831
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
832
|
+
// CIL[END chunk_id="schemautils_sanitizeolor_1784020784"]
|
|
833
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeile_1784020784" type="function" identity="sanitizeFile" parent="none"]
|
|
834
|
+
// CIL[DOC-MACRO purpose="Validate file objects and metadata"]
|
|
835
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure file data validity and constraints"]
|
|
836
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
837
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated file object" errors="file validation errors" side_effects="none"]
|
|
838
|
+
// CIL[DOC-MICRO logic_summary="Checks object structure, size, type, sanitizes filename" notable_decisions="[]"]
|
|
839
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
840
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
841
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
842
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
843
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
844
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
845
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
846
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
759
847
|
function sanitizeFile(data: any, validation?: any): any {
|
|
760
|
-
// Basic file validation - would need more sophisticated handling in practice
|
|
761
848
|
if (typeof data !== 'object' || !data.name) {
|
|
762
849
|
throw new Error('Invalid file data')
|
|
763
850
|
}
|
|
764
851
|
|
|
765
|
-
// Validate file size
|
|
766
852
|
if (validation?.maxSize && data.size > validation.maxSize) {
|
|
767
853
|
throw new Error(`File size exceeds maximum of ${validation.maxSize} bytes`)
|
|
768
854
|
}
|
|
769
855
|
|
|
770
|
-
// Validate file type
|
|
771
856
|
if (validation?.allowedTypes && !validation.allowedTypes.includes(data.type)) {
|
|
772
857
|
throw new Error(`File type ${data.type} is not allowed`)
|
|
773
858
|
}
|
|
774
859
|
|
|
775
|
-
// Sanitize filename
|
|
776
860
|
data.name = data.name.replace(/[^a-zA-Z0-9.-]/g, '_')
|
|
777
861
|
|
|
778
862
|
return data
|
|
779
863
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
864
|
+
// CIL[END chunk_id="schemautils_sanitizeile_1784020784"]
|
|
865
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeimage_1784020784" type="function" identity="sanitizeImage" parent="none"]
|
|
866
|
+
// CIL[DOC-MACRO purpose="Validate image files with dimensions"]
|
|
867
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Extend file sanitization for image-specific validation"]
|
|
868
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
869
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated image object" errors="image validation errors" side_effects="none"]
|
|
870
|
+
// CIL[DOC-MICRO logic_summary="Uses file sanitizer, placeholder for dimension validation" notable_decisions="[]"]
|
|
871
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
872
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
873
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
874
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
875
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
876
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
877
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
878
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
786
879
|
function sanitizeImage(data: any, validation?: any): any {
|
|
787
880
|
const file = sanitizeFile(data, validation)
|
|
788
881
|
|
|
789
|
-
// Additional image-specific validation
|
|
790
882
|
if (validation?.maxWidth || validation?.maxHeight) {
|
|
791
|
-
// Would need to actually load and check image dimensions
|
|
792
|
-
// For now, just pass through
|
|
793
883
|
}
|
|
794
884
|
|
|
795
885
|
return file
|
|
796
886
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
887
|
+
// CIL[END chunk_id="schemautils_sanitizeimage_1784020784"]
|
|
888
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizejson_1784020784" type="function" identity="sanitizeJson" parent="none"]
|
|
889
|
+
// CIL[DOC-MACRO purpose="Parse and sanitize JSON data"]
|
|
890
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure JSON validity and remove dangerous content"]
|
|
891
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
892
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="parsed JSON object" errors="JSON parsing/security errors" side_effects="none"]
|
|
893
|
+
// CIL[DOC-MICRO logic_summary="Parses string JSON, checks for dangerous keywords" notable_decisions="[]"]
|
|
894
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
895
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
896
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
897
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
898
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
899
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
900
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
901
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
803
902
|
function sanitizeJson(data: any, validation?: any): any {
|
|
804
903
|
if (typeof data === 'string') {
|
|
805
904
|
try {
|
|
@@ -809,7 +908,6 @@ function sanitizeJson(data: any, validation?: any): any {
|
|
|
809
908
|
}
|
|
810
909
|
}
|
|
811
910
|
|
|
812
|
-
// Basic security check - prevent code injection
|
|
813
911
|
const jsonStr = JSON.stringify(data)
|
|
814
912
|
if (jsonStr.includes('function') || jsonStr.includes('eval') || jsonStr.includes('script')) {
|
|
815
913
|
throw new Error('JSON contains potentially dangerous content')
|
|
@@ -817,37 +915,51 @@ function sanitizeJson(data: any, validation?: any): any {
|
|
|
817
915
|
|
|
818
916
|
return data
|
|
819
917
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
918
|
+
// CIL[END chunk_id="schemautils_sanitizejson_1784020784"]
|
|
919
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizereference_1784020784" type="function" identity="sanitizeReference" parent="none"]
|
|
920
|
+
// CIL[DOC-MACRO purpose="Validate UUID reference format"]
|
|
921
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Ensure reference follows UUID pattern"]
|
|
922
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
923
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="validated UUID string" errors="invalid UUID error" side_effects="none"]
|
|
924
|
+
// CIL[DOC-MICRO logic_summary="Validates against UUID regex pattern, trims whitespace" notable_decisions="[]"]
|
|
925
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
926
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
927
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
928
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
929
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
930
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
931
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
932
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
825
933
|
function sanitizeReference(data: any, validation?: any): string {
|
|
826
934
|
let ref = String(data).trim()
|
|
827
935
|
|
|
828
|
-
// Validate UUID format
|
|
829
936
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
830
937
|
if (!uuidRegex.test(ref)) {
|
|
831
938
|
throw new Error('Invalid reference format')
|
|
832
939
|
}
|
|
833
940
|
|
|
834
|
-
// Would need to check existence in referenced table
|
|
835
|
-
// For now, just validate format
|
|
836
|
-
|
|
837
941
|
return ref
|
|
838
942
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
943
|
+
// CIL[END chunk_id="schemautils_sanitizereference_1784020784"]
|
|
944
|
+
// CIL[BEGIN chunk_id="schemautils_sanitizeaddress_1784020784" type="function" identity="sanitizeAddress" parent="none"]
|
|
945
|
+
// CIL[DOC-MACRO purpose="Sanitize address object data"]
|
|
946
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Clean address fields and validate structure"]
|
|
947
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
948
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="sanitized address object" errors="invalid address error" side_effects="none"]
|
|
949
|
+
// CIL[DOC-MICRO logic_summary="Validates object type, sanitizes string fields with text sanitizer" notable_decisions="[]"]
|
|
950
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
951
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
952
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
953
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
954
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
955
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
956
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
957
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
845
958
|
function sanitizeAddress(data: any, validation?: any): any {
|
|
846
959
|
if (typeof data !== 'object' || data === null) {
|
|
847
960
|
throw new Error('Address must be an object')
|
|
848
961
|
}
|
|
849
962
|
|
|
850
|
-
// Sanitize each address component
|
|
851
963
|
const sanitized: any = {}
|
|
852
964
|
for (const [key, value] of Object.entries(data)) {
|
|
853
965
|
if (typeof value === 'string') {
|
|
@@ -859,15 +971,39 @@ function sanitizeAddress(data: any, validation?: any): any {
|
|
|
859
971
|
|
|
860
972
|
return sanitized
|
|
861
973
|
}
|
|
862
|
-
|
|
863
|
-
//
|
|
864
|
-
|
|
865
|
-
|
|
974
|
+
// CIL[END chunk_id="schemautils_sanitizeaddress_1784020784"]
|
|
975
|
+
// CIL[BEGIN chunk_id="schemautils_formatjson_1784020784" type="function" identity="formatJson" parent="none"]
|
|
976
|
+
// CIL[DOC-MACRO purpose="Format JSON with pretty printing"]
|
|
977
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert JSON to readable string format"]
|
|
978
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
979
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted JSON string" errors="none" side_effects="none"]
|
|
980
|
+
// CIL[DOC-MICRO logic_summary="Uses JSON.stringify with 2-space indentation" notable_decisions="[]"]
|
|
981
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
982
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
983
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
984
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
985
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
986
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
987
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
988
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
866
989
|
function formatJson(data: any): string {
|
|
867
990
|
return JSON.stringify(data, null, 2)
|
|
868
991
|
}
|
|
869
|
-
|
|
870
|
-
|
|
992
|
+
// CIL[END chunk_id="schemautils_formatjson_1784020784"]
|
|
993
|
+
// CIL[BEGIN chunk_id="schemautils_formatdate_1784020784" type="function" identity="formatDate" parent="none"]
|
|
994
|
+
// CIL[DOC-MACRO purpose="Format dates for display"]
|
|
995
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert date to human-readable format"]
|
|
996
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
997
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted date string" errors="none" side_effects="none"]
|
|
998
|
+
// CIL[DOC-MICRO logic_summary="Uses toLocaleDateString with long month format" notable_decisions="[]"]
|
|
999
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1000
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1001
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1002
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1003
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1004
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1005
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1006
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
871
1007
|
function formatDate(data: string): string {
|
|
872
1008
|
const date = new Date(data)
|
|
873
1009
|
if (isNaN(date.getTime())) {
|
|
@@ -880,8 +1016,21 @@ function formatDate(data: string): string {
|
|
|
880
1016
|
day: 'numeric'
|
|
881
1017
|
})
|
|
882
1018
|
}
|
|
883
|
-
|
|
884
|
-
|
|
1019
|
+
// CIL[END chunk_id="schemautils_formatdate_1784020784"]
|
|
1020
|
+
// CIL[BEGIN chunk_id="schemautils_formatdatetime_1784020784" type="function" identity="formatDatetime" parent="none"]
|
|
1021
|
+
// CIL[DOC-MACRO purpose="Format datetime for display"]
|
|
1022
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert datetime to human-readable format"]
|
|
1023
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1024
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted datetime string" errors="none" side_effects="none"]
|
|
1025
|
+
// CIL[DOC-MICRO logic_summary="Uses toLocaleString with date and time components" notable_decisions="[]"]
|
|
1026
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1027
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1028
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1029
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1030
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1031
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1032
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1033
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
885
1034
|
function formatDatetime(data: string): string {
|
|
886
1035
|
const date = new Date(data)
|
|
887
1036
|
if (isNaN(date.getTime())) {
|
|
@@ -896,8 +1045,21 @@ function formatDatetime(data: string): string {
|
|
|
896
1045
|
minute: '2-digit'
|
|
897
1046
|
})
|
|
898
1047
|
}
|
|
899
|
-
|
|
900
|
-
|
|
1048
|
+
// CIL[END chunk_id="schemautils_formatdatetime_1784020784"]
|
|
1049
|
+
// CIL[BEGIN chunk_id="schemautils_formatcurrency_1784020784" type="function" identity="formatCurrency" parent="none"]
|
|
1050
|
+
// CIL[DOC-MACRO purpose="Format currency with locale"]
|
|
1051
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Format numbers as currency strings"]
|
|
1052
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1053
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted currency string" errors="none" side_effects="none"]
|
|
1054
|
+
// CIL[DOC-MICRO logic_summary="Uses Intl.NumberFormat with currency style" notable_decisions="[]"]
|
|
1055
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1056
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1057
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1058
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1059
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1060
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1061
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1062
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
901
1063
|
function formatCurrency(data: number, context?: any): string {
|
|
902
1064
|
const currency = context?.currency_code || 'USD'
|
|
903
1065
|
return new Intl.NumberFormat('en-US', {
|
|
@@ -905,10 +1067,22 @@ function formatCurrency(data: number, context?: any): string {
|
|
|
905
1067
|
currency: currency
|
|
906
1068
|
}).format(data)
|
|
907
1069
|
}
|
|
908
|
-
|
|
909
|
-
|
|
1070
|
+
// CIL[END chunk_id="schemautils_formatcurrency_1784020784"]
|
|
1071
|
+
// CIL[BEGIN chunk_id="schemautils_formatphone_1784020784" type="function" identity="formatPhone" parent="none"]
|
|
1072
|
+
// CIL[DOC-MACRO purpose="Format phone numbers for display"]
|
|
1073
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Format phone numbers in standard US format"]
|
|
1074
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1075
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted phone string" errors="none" side_effects="none"]
|
|
1076
|
+
// CIL[DOC-MICRO logic_summary="Formats 10-digit and 11-digit US phone numbers" notable_decisions="[]"]
|
|
1077
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1078
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1079
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1080
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1081
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1082
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1083
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1084
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
910
1085
|
function formatPhone(data: string): string {
|
|
911
|
-
// Basic US phone formatting
|
|
912
1086
|
const phone = data.replace(/\D/g, '')
|
|
913
1087
|
if (phone.length === 10) {
|
|
914
1088
|
return `(${phone.slice(0, 3)}) ${phone.slice(3, 6)}-${phone.slice(6)}`
|
|
@@ -918,20 +1092,57 @@ function formatPhone(data: string): string {
|
|
|
918
1092
|
|
|
919
1093
|
return data
|
|
920
1094
|
}
|
|
921
|
-
|
|
922
|
-
|
|
1095
|
+
// CIL[END chunk_id="schemautils_formatphone_1784020784"]
|
|
1096
|
+
// CIL[BEGIN chunk_id="schemautils_formaturl_1784020784" type="function" identity="formatUrl" parent="none"]
|
|
1097
|
+
// CIL[DOC-MACRO purpose="Format URLs for display"]
|
|
1098
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Return URL data unchanged"]
|
|
1099
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1100
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="URL string" errors="none" side_effects="none"]
|
|
1101
|
+
// CIL[DOC-MICRO logic_summary="Pass-through function, no formatting applied" notable_decisions="[]"]
|
|
1102
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1103
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1104
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1105
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1106
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1107
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1108
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1109
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
923
1110
|
function formatUrl(data: string): string {
|
|
924
1111
|
return data
|
|
925
1112
|
}
|
|
926
|
-
|
|
927
|
-
|
|
1113
|
+
// CIL[END chunk_id="schemautils_formaturl_1784020784"]
|
|
1114
|
+
// CIL[BEGIN chunk_id="schemautils_formatreference_1784020784" type="function" identity="formatReference" parent="none"]
|
|
1115
|
+
// CIL[DOC-MACRO purpose="Format references for display"]
|
|
1116
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Return reference data unchanged"]
|
|
1117
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1118
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="reference string" errors="none" side_effects="none"]
|
|
1119
|
+
// CIL[DOC-MICRO logic_summary="Pass-through function, no formatting applied" notable_decisions="[]"]
|
|
1120
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1121
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1122
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1123
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1124
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1125
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1126
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1127
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
928
1128
|
function formatReference(data: string, context?: any): string {
|
|
929
|
-
// Would need to look up the referenced entity
|
|
930
|
-
// For now, return the UUID
|
|
931
1129
|
return data
|
|
932
1130
|
}
|
|
933
|
-
|
|
934
|
-
|
|
1131
|
+
// CIL[END chunk_id="schemautils_formatreference_1784020784"]
|
|
1132
|
+
// CIL[BEGIN chunk_id="schemautils_formataddress_1784020784" type="function" identity="formatAddress" parent="none"]
|
|
1133
|
+
// CIL[DOC-MACRO purpose="Format address objects as strings"]
|
|
1134
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert address object to comma-separated string"]
|
|
1135
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1136
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted address string" errors="none" side_effects="none"]
|
|
1137
|
+
// CIL[DOC-MICRO logic_summary="Joins address components with commas, filters empty values" notable_decisions="[]"]
|
|
1138
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1139
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1140
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1141
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1142
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1143
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1144
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1145
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
935
1146
|
function formatAddress(data: any): string {
|
|
936
1147
|
if (typeof data !== 'object' || data === null) {
|
|
937
1148
|
return String(data)
|
|
@@ -947,8 +1158,21 @@ function formatAddress(data: any): string {
|
|
|
947
1158
|
|
|
948
1159
|
return parts.join(', ')
|
|
949
1160
|
}
|
|
950
|
-
|
|
951
|
-
|
|
1161
|
+
// CIL[END chunk_id="schemautils_formataddress_1784020784"]
|
|
1162
|
+
// CIL[BEGIN chunk_id="schemautils_formatmultiselect_1784020784" type="function" identity="formatMultiselect" parent="none"]
|
|
1163
|
+
// CIL[DOC-MACRO purpose="Format multiselect arrays as strings"]
|
|
1164
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert array to comma-separated string"]
|
|
1165
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1166
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="comma-separated string" errors="none" side_effects="none"]
|
|
1167
|
+
// CIL[DOC-MICRO logic_summary="Joins array elements with commas, handles non-arrays" notable_decisions="[]"]
|
|
1168
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1169
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1170
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1171
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1172
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1173
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1174
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1175
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
952
1176
|
function formatMultiselect(data: string[]): string {
|
|
953
1177
|
if (!Array.isArray(data)) {
|
|
954
1178
|
return String(data)
|
|
@@ -956,8 +1180,21 @@ function formatMultiselect(data: string[]): string {
|
|
|
956
1180
|
|
|
957
1181
|
return data.join(', ')
|
|
958
1182
|
}
|
|
959
|
-
|
|
960
|
-
|
|
1183
|
+
// CIL[END chunk_id="schemautils_formatmultiselect_1784020784"]
|
|
1184
|
+
// CIL[BEGIN chunk_id="schemautils_formatboolean_1784020784" type="function" identity="formatBoolean" parent="none"]
|
|
1185
|
+
// CIL[DOC-MACRO purpose="Format booleans with contextual labels"]
|
|
1186
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Convert boolean to human-readable labels"]
|
|
1187
|
+
// CIL[DOC-CONTEXT module="schema-utils" layer="shared" related_files="[]"]
|
|
1188
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="formatted boolean string" errors="none" side_effects="none"]
|
|
1189
|
+
// CIL[DOC-MICRO logic_summary="Uses contextual labels for is_active, defaults to Yes/No" notable_decisions="[]"]
|
|
1190
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
1191
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
1192
|
+
// CIL[DOC-VECTOR type="context" content="Layer: shared. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
1193
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
1194
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
1195
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
1196
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
1197
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
961
1198
|
function formatBoolean(data: boolean, context?: any): string {
|
|
962
1199
|
if (context?.field === 'is_active') {
|
|
963
1200
|
return data ? 'Active' : 'Inactive'
|
|
@@ -965,3 +1202,4 @@ function formatBoolean(data: boolean, context?: any): string {
|
|
|
965
1202
|
|
|
966
1203
|
return data ? 'Yes' : 'No'
|
|
967
1204
|
}
|
|
1205
|
+
// CIL[END chunk_id="schemautils_formatboolean_1784020784"]
|