@terpjs/spec 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +417 -417
- package/VERSION +1 -1
- package/app-check-report.schema.json +122 -122
- package/assurance-profile.schema.json +70 -70
- package/catalog/backend/alembic_downgrades_not_empty.json +22 -22
- package/catalog/backend/base_query_not_overridden.json +27 -27
- package/catalog/backend/canonical_module_shape.json +22 -22
- package/catalog/backend/datetime_columns_are_timezone_aware.json +23 -23
- package/catalog/backend/escape_hatch_budget.json +21 -21
- package/catalog/backend/events_reference_catalog.json +27 -27
- package/catalog/backend/input_schemas_exclude_managed_columns.json +27 -27
- package/catalog/backend/input_str_fields_have_max_length.json +22 -22
- package/catalog/backend/jobs_reference_catalog.json +27 -27
- package/catalog/backend/list_routes_paginate.json +32 -32
- package/catalog/backend/modules_declare_policy.json +26 -26
- package/catalog/backend/mutations_emit_audit.json +26 -26
- package/catalog/backend/mutations_require_write_role.json +32 -32
- package/catalog/backend/no_adhoc_background_runtime.json +22 -22
- package/catalog/backend/no_adhoc_config_decrypt.json +27 -27
- package/catalog/backend/no_adhoc_logging_config.json +22 -22
- package/catalog/backend/no_adhoc_middleware.json +27 -27
- package/catalog/backend/no_adhoc_permission_literals.json +27 -27
- package/catalog/backend/no_app_instantiation.json +22 -22
- package/catalog/backend/no_blocking_sleep.json +22 -22
- package/catalog/backend/no_cross_module_imports.json +21 -21
- package/catalog/backend/no_dependency_overrides.json +27 -27
- package/catalog/backend/no_destructive_migrations.json +22 -22
- package/catalog/backend/no_dynamic_sql.json +22 -22
- package/catalog/backend/no_empty_tests.json +22 -22
- package/catalog/backend/no_eval_or_exec.json +22 -22
- package/catalog/backend/no_hardcoded_credentials.json +21 -21
- package/catalog/backend/no_internal_imports.json +22 -22
- package/catalog/backend/no_manual_actor_stamping.json +27 -27
- package/catalog/backend/no_manual_ownership_checks.json +32 -32
- package/catalog/backend/no_manual_scope_filtering.json +27 -27
- package/catalog/backend/no_manual_table_schema.json +22 -22
- package/catalog/backend/no_manual_version_assignment.json +22 -22
- package/catalog/backend/no_mutable_default_args.json +22 -22
- package/catalog/backend/no_naive_datetime.json +22 -22
- package/catalog/backend/no_oversized_python_files.json +22 -22
- package/catalog/backend/no_print.json +22 -22
- package/catalog/backend/no_raw_app_routes.json +26 -26
- package/catalog/backend/no_raw_connection_access.json +27 -27
- package/catalog/backend/no_raw_file_references.json +27 -27
- package/catalog/backend/no_raw_outbound_http.json +22 -22
- package/catalog/backend/no_raw_session_construction.json +22 -22
- package/catalog/backend/no_star_imports.json +22 -22
- package/catalog/backend/no_todo_fixme.json +22 -22
- package/catalog/backend/no_unique_columns_on_soft_delete_models.json +22 -22
- package/catalog/backend/offset_queries_declare_ordering.json +22 -22
- package/catalog/backend/path_id_params_are_uuid.json +22 -22
- package/catalog/backend/policy_refs_resolve.json +27 -27
- package/catalog/backend/public_modules_are_read_only.json +26 -26
- package/catalog/backend/reads_use_base_query.json +27 -27
- package/catalog/backend/response_model_not_table_model.json +27 -27
- package/catalog/backend/routes_declare_response_model.json +27 -27
- package/catalog/backend/safe_methods_are_read_only.json +31 -31
- package/catalog/backend/schemas_exclude_sensitive_fields.json +32 -32
- package/catalog/backend/session_imported_from_sqlmodel.json +22 -22
- package/catalog/backend/table_models_use_base_table.json +22 -22
- package/catalog/backend/tables_have_migrations.json +27 -27
- package/catalog/backend/tenant_scoped_models_use_scoped_service.json +22 -22
- package/catalog/backend/ungoverned_escape_hatch.json +21 -21
- package/catalog/backend/update_schemas_inherit_base_update_schema.json +32 -32
- package/catalog/frontend/escape-hatch.json +21 -21
- package/catalog/frontend/generated-client-only.json +26 -26
- package/catalog/frontend/layout-contract.json +26 -26
- package/catalog/frontend/no-cross-module-imports.json +21 -21
- package/catalog/frontend/no-deep-imports.json +25 -25
- package/catalog/frontend/no-dom-html-injection.json +22 -22
- package/catalog/frontend/no-eval.json +21 -21
- package/catalog/frontend/no-inline-styling.json +25 -25
- package/catalog/frontend/no-style-imports.json +24 -24
- package/catalog/frontend/no-unsafe-href.json +21 -21
- package/catalog/frontend/no-unsafe-target-blank.json +21 -21
- package/catalog/frontend/router-links.json +22 -22
- package/catalog/frontend/token-styled-elements.json +25 -25
- package/catalog/schema.json +95 -95
- package/corpus/PENDING.json +4 -4
- package/corpus/RESIDUALS.json +21 -21
- package/corpus/backend/alembic_downgrades_not_empty/compliant-01/modules/notes/migrations/versions/0001_change.py +6 -6
- package/corpus/backend/alembic_downgrades_not_empty/violation-01/modules/notes/migrations/versions/0001_change.py +6 -6
- package/corpus/backend/base_query_not_overridden/compliant-01/modules/notes/service.py +8 -8
- package/corpus/backend/base_query_not_overridden/compliant-02/modules/notes/service.py +8 -8
- package/corpus/backend/base_query_not_overridden/violation-01/modules/notes/service.py +8 -8
- package/corpus/backend/base_query_not_overridden/violation-02/expected-findings.json +7 -7
- package/corpus/backend/base_query_not_overridden/violation-02/modules/notes/service.py +8 -8
- package/corpus/backend/canonical_module_shape/compliant-01/modules/notes/models.py +6 -6
- package/corpus/backend/canonical_module_shape/compliant-01/modules/notes/module.py +7 -7
- package/corpus/backend/canonical_module_shape/compliant-01/modules/notes/router.py +3 -3
- package/corpus/backend/canonical_module_shape/compliant-01/modules/notes/schemas.py +10 -10
- package/corpus/backend/canonical_module_shape/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/canonical_module_shape/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/datetime_columns_are_timezone_aware/compliant-01/modules/notes/models.py +12 -12
- package/corpus/backend/datetime_columns_are_timezone_aware/violation-01/modules/notes/models.py +12 -12
- package/corpus/backend/datetime_columns_are_timezone_aware/violation-02/modules/notes/models.py +13 -13
- package/corpus/backend/datetime_columns_are_timezone_aware/violation-03/modules/notes/models.py +15 -15
- package/corpus/backend/escape_hatch_budget/compliant-01/escape-hatch-budget.json +3 -3
- package/corpus/backend/escape_hatch_budget/compliant-01/modules/notes/service.py +2 -2
- package/corpus/backend/escape_hatch_budget/compliant-02/escape-hatch-budget.json +1 -1
- package/corpus/backend/escape_hatch_budget/compliant-02/modules/notes/service.py +4 -4
- package/corpus/backend/escape_hatch_budget/violation-01/escape-hatch-budget.json +1 -1
- package/corpus/backend/escape_hatch_budget/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/escape_hatch_budget/violation-02/escape-hatch-budget.json +3 -3
- package/corpus/backend/escape_hatch_budget/violation-02/modules/notes/service.py +4 -4
- package/corpus/backend/events_reference_catalog/compliant-01/modules/notes/module.py +9 -9
- package/corpus/backend/events_reference_catalog/violation-01/modules/notes/module.py +8 -8
- package/corpus/backend/input_schemas_exclude_managed_columns/compliant-01/modules/notes/schemas.py +6 -6
- package/corpus/backend/input_schemas_exclude_managed_columns/violation-01/expected-findings.json +7 -7
- package/corpus/backend/input_schemas_exclude_managed_columns/violation-01/modules/notes/schemas.py +9 -9
- package/corpus/backend/input_schemas_exclude_managed_columns/violation-02/expected-findings.json +12 -12
- package/corpus/backend/input_schemas_exclude_managed_columns/violation-02/modules/notes/router.py +14 -14
- package/corpus/backend/input_str_fields_have_max_length/compliant-01/modules/notes/schemas.py +4 -4
- package/corpus/backend/input_str_fields_have_max_length/violation-01/modules/notes/schemas.py +2 -2
- package/corpus/backend/jobs_reference_catalog/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/jobs_reference_catalog/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/list_routes_paginate/compliant-01/modules/notes/router.py +6 -6
- package/corpus/backend/list_routes_paginate/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/modules_declare_policy/compliant-01/modules/notes/module.py +7 -7
- package/corpus/backend/modules_declare_policy/violation-01/modules/notes/module.py +6 -6
- package/corpus/backend/mutations_emit_audit/compliant-01/modules/notes/service.py +9 -9
- package/corpus/backend/mutations_emit_audit/violation-01/modules/notes/service.py +4 -4
- package/corpus/backend/mutations_require_write_role/compliant-01/modules/notes/module.py +7 -7
- package/corpus/backend/mutations_require_write_role/compliant-01/modules/notes/router.py +3 -3
- package/corpus/backend/mutations_require_write_role/compliant-02/modules/notes/module.py +7 -7
- package/corpus/backend/mutations_require_write_role/compliant-02/modules/notes/router.py +3 -3
- package/corpus/backend/mutations_require_write_role/violation-01/expected-findings.json +7 -7
- package/corpus/backend/mutations_require_write_role/violation-01/modules/notes/module.py +7 -7
- package/corpus/backend/mutations_require_write_role/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/mutations_require_write_role/violation-02/expected-findings.json +7 -7
- package/corpus/backend/mutations_require_write_role/violation-02/modules/notes/module.py +7 -7
- package/corpus/backend/mutations_require_write_role/violation-02/modules/notes/router.py +5 -5
- package/corpus/backend/mutations_require_write_role/violation-03/expected-findings.json +7 -7
- package/corpus/backend/mutations_require_write_role/violation-03/modules/notes/module.py +10 -10
- package/corpus/backend/mutations_require_write_role/violation-03/modules/notes/router.py +3 -3
- package/corpus/backend/no_adhoc_background_runtime/compliant-01/modules/notes/service.py +9 -9
- package/corpus/backend/no_adhoc_background_runtime/violation-01/modules/notes/service.py +5 -5
- package/corpus/backend/no_adhoc_background_runtime/violation-02/modules/notes/service.py +3 -3
- package/corpus/backend/no_adhoc_config_decrypt/compliant-01/modules/billing/service.py +2 -2
- package/corpus/backend/no_adhoc_config_decrypt/violation-01/modules/billing/service.py +2 -2
- package/corpus/backend/no_adhoc_logging_config/compliant-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_adhoc_logging_config/violation-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_adhoc_middleware/compliant-01/main.py +3 -3
- package/corpus/backend/no_adhoc_middleware/violation-01/main.py +4 -4
- package/corpus/backend/no_adhoc_middleware/violation-02/main.py +5 -5
- package/corpus/backend/no_adhoc_permission_literals/compliant-01/modules/notes/module.py +3 -3
- package/corpus/backend/no_adhoc_permission_literals/compliant-02/modules/notes/router.py +5 -5
- package/corpus/backend/no_adhoc_permission_literals/violation-01/expected-findings.json +7 -7
- package/corpus/backend/no_adhoc_permission_literals/violation-01/modules/notes/module.py +1 -1
- package/corpus/backend/no_adhoc_permission_literals/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_adhoc_permission_literals/violation-02/modules/notes/router.py +2 -2
- package/corpus/backend/no_adhoc_permission_literals/violation-03/expected-findings.json +12 -12
- package/corpus/backend/no_adhoc_permission_literals/violation-03/modules/notes/module.py +10 -10
- package/corpus/backend/no_app_instantiation/compliant-01/main.py +3 -3
- package/corpus/backend/no_app_instantiation/violation-01/main.py +3 -3
- package/corpus/backend/no_blocking_sleep/compliant-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_blocking_sleep/violation-01/modules/notes/service.py +5 -5
- package/corpus/backend/no_cross_module_imports/compliant-01/modules/a/service.py +1 -1
- package/corpus/backend/no_cross_module_imports/violation-01/modules/a/service.py +1 -1
- package/corpus/backend/no_cross_module_imports/violation-02/modules/a/service.py +1 -1
- package/corpus/backend/no_dependency_overrides/compliant-01/main.py +12 -12
- package/corpus/backend/no_dependency_overrides/violation-01/main.py +11 -11
- package/corpus/backend/no_destructive_migrations/compliant-01/modules/notes/migrations/versions/0001_change.py +3 -3
- package/corpus/backend/no_destructive_migrations/compliant-02/modules/notes/migrations/versions/0001_change.py +8 -8
- package/corpus/backend/no_destructive_migrations/violation-01/expected-findings.json +7 -7
- package/corpus/backend/no_destructive_migrations/violation-01/modules/notes/migrations/versions/0001_change.py +2 -2
- package/corpus/backend/no_destructive_migrations/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_destructive_migrations/violation-02/modules/notes/migrations/versions/0001_change.py +2 -2
- package/corpus/backend/no_destructive_migrations/violation-03/expected-findings.json +7 -7
- package/corpus/backend/no_destructive_migrations/violation-03/modules/notes/migrations/versions/0001_change.py +3 -3
- package/corpus/backend/no_destructive_migrations/violation-04/expected-findings.json +12 -12
- package/corpus/backend/no_destructive_migrations/violation-04/modules/notes/migrations/versions/0001_change.py +6 -6
- package/corpus/backend/no_destructive_migrations/violation-05/expected-findings.json +12 -12
- package/corpus/backend/no_destructive_migrations/violation-05/modules/notes/migrations/versions/0001_change.py +3 -3
- package/corpus/backend/no_dynamic_sql/compliant-01/modules/notes/service.py +1 -1
- package/corpus/backend/no_dynamic_sql/compliant-02/modules/notes/service.py +20 -20
- package/corpus/backend/no_dynamic_sql/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_dynamic_sql/violation-02/modules/notes/service.py +2 -2
- package/corpus/backend/no_dynamic_sql/violation-03/modules/notes/service.py +7 -7
- package/corpus/backend/no_dynamic_sql/violation-04/modules/notes/service.py +16 -16
- package/corpus/backend/no_empty_tests/compliant-01/tests/test_notes.py +2 -2
- package/corpus/backend/no_empty_tests/violation-01/tests/test_notes.py +2 -2
- package/corpus/backend/no_eval_or_exec/compliant-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_eval_or_exec/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_hardcoded_credentials/compliant-01/modules/billing/service.py +3 -3
- package/corpus/backend/no_hardcoded_credentials/compliant-02/modules/billing/service.py +18 -18
- package/corpus/backend/no_hardcoded_credentials/violation-01/expected-findings.json +7 -7
- package/corpus/backend/no_hardcoded_credentials/violation-01/modules/billing/service.py +2 -2
- package/corpus/backend/no_hardcoded_credentials/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_hardcoded_credentials/violation-02/modules/billing/service.py +1 -1
- package/corpus/backend/no_hardcoded_credentials/violation-03/expected-findings.json +22 -22
- package/corpus/backend/no_hardcoded_credentials/violation-03/modules/billing/service.py +11 -11
- package/corpus/backend/no_hardcoded_credentials/violation-04/expected-findings.json +12 -12
- package/corpus/backend/no_hardcoded_credentials/violation-04/modules/billing/service.py +8 -8
- package/corpus/backend/no_hardcoded_credentials/violation-05/expected-findings.json +12 -12
- package/corpus/backend/no_hardcoded_credentials/violation-05/modules/billing/service.py +4 -4
- package/corpus/backend/no_internal_imports/compliant-01/modules/notes/service.py +1 -1
- package/corpus/backend/no_internal_imports/violation-01/modules/notes/service.py +1 -1
- package/corpus/backend/no_manual_actor_stamping/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/no_manual_actor_stamping/compliant-02/modules/notes/schemas.py +12 -12
- package/corpus/backend/no_manual_actor_stamping/violation-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_manual_actor_stamping/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_manual_actor_stamping/violation-02/modules/notes/service.py +4 -4
- package/corpus/backend/no_manual_ownership_checks/compliant-01/modules/journals/service.py +3 -3
- package/corpus/backend/no_manual_ownership_checks/compliant-02/modules/journals/schemas.py +11 -11
- package/corpus/backend/no_manual_ownership_checks/violation-01/modules/journals/service.py +3 -3
- package/corpus/backend/no_manual_ownership_checks/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_manual_ownership_checks/violation-02/modules/journals/service.py +9 -9
- package/corpus/backend/no_manual_ownership_checks/violation-03/expected-findings.json +7 -7
- package/corpus/backend/no_manual_ownership_checks/violation-03/modules/notes/jobs.py +1 -1
- package/corpus/backend/no_manual_ownership_checks/violation-03/modules/notes/models.py +7 -7
- package/corpus/backend/no_manual_ownership_checks/violation-03/modules/notes/module.py +11 -11
- package/corpus/backend/no_manual_ownership_checks/violation-03/modules/notes/service.py +7 -7
- package/corpus/backend/no_manual_scope_filtering/compliant-01/modules/notes/service.py +8 -8
- package/corpus/backend/no_manual_scope_filtering/compliant-02/modules/notes/schemas.py +12 -12
- package/corpus/backend/no_manual_scope_filtering/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_manual_scope_filtering/violation-02/modules/notes/service.py +2 -2
- package/corpus/backend/no_manual_scope_filtering/violation-03/expected-findings.json +7 -7
- package/corpus/backend/no_manual_scope_filtering/violation-03/modules/notes/service.py +7 -7
- package/corpus/backend/no_manual_table_schema/compliant-01/modules/notes/models.py +6 -6
- package/corpus/backend/no_manual_table_schema/violation-01/modules/notes/models.py +8 -8
- package/corpus/backend/no_manual_version_assignment/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/no_manual_version_assignment/violation-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_manual_version_assignment/violation-02/modules/notes/service.py +3 -3
- package/corpus/backend/no_manual_version_assignment/violation-03/modules/notes/service.py +3 -3
- package/corpus/backend/no_mutable_default_args/compliant-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_mutable_default_args/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_naive_datetime/compliant-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_naive_datetime/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_naive_datetime/violation-02/modules/notes/service.py +2 -2
- package/corpus/backend/no_oversized_python_files/compliant-01/modules/notes/service.py +9 -9
- package/corpus/backend/no_oversized_python_files/violation-01/modules/notes/service.py +530 -530
- package/corpus/backend/no_print/compliant-01/modules/notes/service.py +7 -7
- package/corpus/backend/no_print/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_raw_app_routes/compliant-01/main.py +12 -12
- package/corpus/backend/no_raw_app_routes/violation-01/main.py +10 -10
- package/corpus/backend/no_raw_app_routes/violation-02/main.py +16 -16
- package/corpus/backend/no_raw_app_routes/violation-03/main.py +12 -12
- package/corpus/backend/no_raw_app_routes/violation-04/main.py +10 -10
- package/corpus/backend/no_raw_app_routes/violation-05/main.py +12 -12
- package/corpus/backend/no_raw_app_routes/violation-06/main.py +10 -10
- package/corpus/backend/no_raw_connection_access/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/no_raw_connection_access/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_raw_connection_access/violation-02/modules/notes/service.py +2 -2
- package/corpus/backend/no_raw_file_references/compliant-01/modules/notes/models.py +10 -10
- package/corpus/backend/no_raw_file_references/violation-01/modules/notes/models.py +9 -9
- package/corpus/backend/no_raw_outbound_http/compliant-01/modules/notes/service.py +2 -2
- package/corpus/backend/no_raw_outbound_http/compliant-03/modules/notes/service.py +12 -12
- package/corpus/backend/no_raw_outbound_http/violation-01/expected-findings.json +7 -7
- package/corpus/backend/no_raw_outbound_http/violation-01/modules/notes/service.py +1 -1
- package/corpus/backend/no_raw_outbound_http/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_raw_outbound_http/violation-02/modules/notes/service.py +1 -1
- package/corpus/backend/no_raw_outbound_http/violation-03/expected-findings.json +7 -7
- package/corpus/backend/no_raw_outbound_http/violation-03/modules/notes/service.py +1 -1
- package/corpus/backend/no_raw_outbound_http/violation-04/expected-findings.json +12 -12
- package/corpus/backend/no_raw_outbound_http/violation-04/modules/notes/service.py +7 -7
- package/corpus/backend/no_raw_outbound_http/violation-05/expected-findings.json +12 -12
- package/corpus/backend/no_raw_outbound_http/violation-05/modules/notes/service.py +5 -5
- package/corpus/backend/no_raw_outbound_http/violation-06/expected-findings.json +12 -12
- package/corpus/backend/no_raw_outbound_http/violation-06/modules/notes/service.py +2 -2
- package/corpus/backend/no_raw_session_construction/compliant-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_raw_session_construction/violation-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_star_imports/compliant-01/modules/notes/service.py +1 -1
- package/corpus/backend/no_star_imports/violation-01/modules/notes/service.py +1 -1
- package/corpus/backend/no_todo_fixme/compliant-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_todo_fixme/violation-01/modules/notes/service.py +3 -3
- package/corpus/backend/no_unique_columns_on_soft_delete_models/compliant-01/modules/notes/models.py +17 -17
- package/corpus/backend/no_unique_columns_on_soft_delete_models/violation-01/expected-findings.json +7 -7
- package/corpus/backend/no_unique_columns_on_soft_delete_models/violation-01/modules/notes/models.py +6 -6
- package/corpus/backend/no_unique_columns_on_soft_delete_models/violation-02/expected-findings.json +7 -7
- package/corpus/backend/no_unique_columns_on_soft_delete_models/violation-02/modules/notes/models.py +13 -13
- package/corpus/backend/no_unique_columns_on_soft_delete_models/violation-03/expected-findings.json +7 -7
- package/corpus/backend/no_unique_columns_on_soft_delete_models/violation-03/modules/notes/models.py +16 -16
- package/corpus/backend/offset_queries_declare_ordering/compliant-01/modules/notes/service.py +4 -4
- package/corpus/backend/offset_queries_declare_ordering/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/path_id_params_are_uuid/compliant-01/modules/notes/router.py +6 -6
- package/corpus/backend/path_id_params_are_uuid/violation-01/modules/notes/router.py +6 -6
- package/corpus/backend/policy_refs_resolve/compliant-01/modules/notes/module.py +7 -7
- package/corpus/backend/policy_refs_resolve/violation-01/modules/notes/module.py +8 -8
- package/corpus/backend/public_modules_are_read_only/compliant-01/modules/notes/module.py +7 -7
- package/corpus/backend/public_modules_are_read_only/compliant-01/modules/notes/router.py +3 -3
- package/corpus/backend/public_modules_are_read_only/violation-01/expected-findings.json +7 -7
- package/corpus/backend/public_modules_are_read_only/violation-01/modules/notes/module.py +7 -7
- package/corpus/backend/public_modules_are_read_only/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/public_modules_are_read_only/violation-02/expected-findings.json +7 -7
- package/corpus/backend/public_modules_are_read_only/violation-02/modules/notes/module.py +7 -7
- package/corpus/backend/public_modules_are_read_only/violation-02/modules/notes/router.py +5 -5
- package/corpus/backend/reads_use_base_query/compliant-01/modules/notes/models.py +6 -6
- package/corpus/backend/reads_use_base_query/compliant-01/modules/notes/service.py +8 -8
- package/corpus/backend/reads_use_base_query/compliant-02/modules/notes/models.py +9 -9
- package/corpus/backend/reads_use_base_query/compliant-02/modules/notes/service.py +9 -9
- package/corpus/backend/reads_use_base_query/violation-01/modules/notes/models.py +6 -6
- package/corpus/backend/reads_use_base_query/violation-01/modules/notes/service.py +9 -9
- package/corpus/backend/reads_use_base_query/violation-02/expected-findings.json +7 -7
- package/corpus/backend/reads_use_base_query/violation-02/modules/notes/models.py +6 -6
- package/corpus/backend/reads_use_base_query/violation-02/modules/notes/service.py +8 -8
- package/corpus/backend/response_model_not_table_model/compliant-01/modules/notes/models.py +6 -6
- package/corpus/backend/response_model_not_table_model/compliant-01/modules/notes/router.py +3 -3
- package/corpus/backend/response_model_not_table_model/compliant-01/modules/notes/schemas.py +5 -5
- package/corpus/backend/response_model_not_table_model/violation-01/modules/notes/models.py +6 -6
- package/corpus/backend/response_model_not_table_model/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/routes_declare_response_model/compliant-01/modules/notes/router.py +8 -8
- package/corpus/backend/routes_declare_response_model/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/safe_methods_are_read_only/compliant-01/modules/notes/router.py +6 -6
- package/corpus/backend/safe_methods_are_read_only/compliant-02/modules/notes/router.py +5 -5
- package/corpus/backend/safe_methods_are_read_only/violation-01/expected-findings.json +7 -7
- package/corpus/backend/safe_methods_are_read_only/violation-01/modules/notes/router.py +3 -3
- package/corpus/backend/safe_methods_are_read_only/violation-02/expected-findings.json +7 -7
- package/corpus/backend/safe_methods_are_read_only/violation-02/modules/notes/router.py +5 -5
- package/corpus/backend/safe_methods_are_read_only/violation-03/expected-findings.json +7 -7
- package/corpus/backend/safe_methods_are_read_only/violation-03/modules/notes/router.py +3 -3
- package/corpus/backend/schemas_exclude_sensitive_fields/compliant-01/modules/users/schemas.py +5 -5
- package/corpus/backend/schemas_exclude_sensitive_fields/compliant-02/modules/accounts/schemas.py +12 -12
- package/corpus/backend/schemas_exclude_sensitive_fields/violation-01/expected-findings.json +7 -7
- package/corpus/backend/schemas_exclude_sensitive_fields/violation-01/modules/users/schemas.py +3 -3
- package/corpus/backend/schemas_exclude_sensitive_fields/violation-02/expected-findings.json +7 -7
- package/corpus/backend/schemas_exclude_sensitive_fields/violation-02/modules/connectors/router.py +8 -8
- package/corpus/backend/schemas_exclude_sensitive_fields/violation-03/expected-findings.json +17 -17
- package/corpus/backend/schemas_exclude_sensitive_fields/violation-03/modules/integrations/schemas.py +7 -7
- package/corpus/backend/session_imported_from_sqlmodel/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/session_imported_from_sqlmodel/violation-01/modules/notes/service.py +5 -5
- package/corpus/backend/table_models_use_base_table/compliant-01/modules/notes/models.py +6 -6
- package/corpus/backend/table_models_use_base_table/violation-01/modules/notes/models.py +5 -5
- package/corpus/backend/tables_have_migrations/compliant-01/modules/notes/migrations/versions/0a1b2c3d4e5f_create_notes_tables.py +22 -22
- package/corpus/backend/tables_have_migrations/compliant-01/modules/notes/models.py +6 -6
- package/corpus/backend/tables_have_migrations/compliant-02/capabilities/ledger/models.py +6 -6
- package/corpus/backend/tables_have_migrations/violation-01/expected-findings.json +7 -7
- package/corpus/backend/tables_have_migrations/violation-01/modules/notes/models.py +6 -6
- package/corpus/backend/tables_have_migrations/violation-02/expected-findings.json +7 -7
- package/corpus/backend/tables_have_migrations/violation-02/modules/notes/models.py +10 -10
- package/corpus/backend/tenant_scoped_models_use_scoped_service/compliant-01/modules/projects/models.py +6 -6
- package/corpus/backend/tenant_scoped_models_use_scoped_service/compliant-01/modules/projects/service.py +5 -5
- package/corpus/backend/tenant_scoped_models_use_scoped_service/compliant-02/modules/projects/models.py +8 -8
- package/corpus/backend/tenant_scoped_models_use_scoped_service/compliant-02/modules/projects/service.py +5 -5
- package/corpus/backend/tenant_scoped_models_use_scoped_service/violation-01/modules/projects/models.py +6 -6
- package/corpus/backend/tenant_scoped_models_use_scoped_service/violation-01/modules/projects/service.py +5 -5
- package/corpus/backend/ungoverned_escape_hatch/compliant-01/modules/notes/service.py +5 -5
- package/corpus/backend/ungoverned_escape_hatch/compliant-02/modules/notes/service.py +4 -4
- package/corpus/backend/ungoverned_escape_hatch/violation-01/modules/notes/service.py +2 -2
- package/corpus/backend/update_schemas_inherit_base_update_schema/compliant-01/modules/notes/schemas.py +2 -2
- package/corpus/backend/update_schemas_inherit_base_update_schema/violation-01/modules/notes/schemas.py +2 -2
- package/corpus/backend/update_schemas_inherit_base_update_schema/violation-02/modules/notes/schemas.py +5 -5
- package/corpus/frontend/escape-hatch/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/escape-hatch/violation-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/escape-hatch/violation-02/src/modules/widgets/Widget.tsx +7 -7
- package/corpus/frontend/escape-hatch/violation-03/src/modules/widgets/Widget.tsx +7 -7
- package/corpus/frontend/generated-client-only/compliant-01/src/modules/widgets/Widget.tsx +6 -6
- package/corpus/frontend/generated-client-only/compliant-02/src/modules/widgets/Widget.tsx +21 -21
- package/corpus/frontend/generated-client-only/compliant-03/src/modules/widgets/Widget.tsx +7 -7
- package/corpus/frontend/generated-client-only/compliant-04/src/modules/widgets/Widget.tsx +17 -17
- package/corpus/frontend/generated-client-only/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/generated-client-only/violation-02/src/modules/widgets/Widget.tsx +9 -9
- package/corpus/frontend/generated-client-only/violation-03/src/modules/widgets/Widget.tsx +14 -14
- package/corpus/frontend/generated-client-only/violation-04/src/modules/widgets/Widget.tsx +6 -6
- package/corpus/frontend/layout-contract/compliant-01/layout-contract.json +3 -3
- package/corpus/frontend/layout-contract/compliant-01/src/modules/widgets/Widget.tsx +8 -8
- package/corpus/frontend/layout-contract/violation-01/layout-contract.json +3 -3
- package/corpus/frontend/layout-contract/violation-01/src/modules/widgets/Widget.tsx +8 -8
- package/corpus/frontend/no-cross-module-imports/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/no-cross-module-imports/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-deep-imports/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/no-deep-imports/violation-01/src/modules/widgets/Widget.tsx +2 -2
- package/corpus/frontend/no-dom-html-injection/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/no-dom-html-injection/compliant-02/src/modules/widgets/Widget.tsx +11 -11
- package/corpus/frontend/no-dom-html-injection/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-dom-html-injection/violation-02/src/modules/widgets/Widget.tsx +7 -7
- package/corpus/frontend/no-dom-html-injection/violation-03/src/modules/widgets/Widget.tsx +12 -12
- package/corpus/frontend/no-eval/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/no-eval/compliant-02/src/modules/widgets/Widget.tsx +11 -11
- package/corpus/frontend/no-eval/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-eval/violation-02/src/modules/widgets/Widget.tsx +7 -7
- package/corpus/frontend/no-eval/violation-03/src/modules/widgets/Widget.tsx +10 -10
- package/corpus/frontend/no-eval/violation-04/src/modules/widgets/Widget.tsx +6 -6
- package/corpus/frontend/no-inline-styling/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/no-inline-styling/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-inline-styling/violation-02/src/modules/widgets/Widget.tsx +6 -6
- package/corpus/frontend/no-style-imports/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/no-style-imports/violation-01/src/modules/widgets/Widget.tsx +2 -2
- package/corpus/frontend/no-unsafe-href/compliant-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-unsafe-href/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-unsafe-target-blank/compliant-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/no-unsafe-target-blank/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/router-links/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/router-links/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/corpus/frontend/token-styled-elements/compliant-01/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/token-styled-elements/compliant-02/src/modules/widgets/Widget.tsx +4 -4
- package/corpus/frontend/token-styled-elements/violation-01/src/modules/widgets/Widget.tsx +3 -3
- package/findings.schema.json +40 -40
- package/package.json +23 -23
- package/restricted-surface.json +10 -10
- package/scorecard.schema.json +52 -52
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/generated-client-only",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "All network egress goes through the generated, typed client",
|
|
5
|
-
"intent": "Raw fetch / XMLHttpRequest / WebSocket / EventSource (and navigator.sendBeacon) bypass the app's single audited, typed egress path. One client means one place for auth, errors, and contract types. The refused globals and member calls are declared in restricted-surface.json (restrictedGlobals, restrictedMemberCalls).",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "BOUNDARY_SPEC.restrictedGlobals",
|
|
12
|
-
"reported_as": "no-restricted-globals"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"reference": "useTerpClient() + unwrap from @terp/react-core for request/response; useRealtimeChannel() from @terp/react-core for typed SSE/WebSocket subscriptions (one-use ticket minted through the generated client).",
|
|
16
|
-
"opt_out": "// terp-allow-generated-client-only: <reason>",
|
|
17
|
-
"runtime": {
|
|
18
|
-
"applicability": "not-applicable",
|
|
19
|
-
"rationale": "In the running bundle the sanctioned generated client is itself built on fetch, so egress-primitive use cannot be attributed to an app module from inside the app. One typed egress path is an authoring contract; network policy beyond it (CSP connect-src) is deployment configuration the framework does not own per module."
|
|
20
|
-
},
|
|
21
|
-
"restricted_surface": [
|
|
22
|
-
"restrictedGlobals",
|
|
23
|
-
"restrictedMemberCalls"
|
|
24
|
-
],
|
|
25
|
-
"corpus": true
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/generated-client-only",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "All network egress goes through the generated, typed client",
|
|
5
|
+
"intent": "Raw fetch / XMLHttpRequest / WebSocket / EventSource (and navigator.sendBeacon) bypass the app's single audited, typed egress path. One client means one place for auth, errors, and contract types. The refused globals and member calls are declared in restricted-surface.json (restrictedGlobals, restrictedMemberCalls).",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "BOUNDARY_SPEC.restrictedGlobals",
|
|
12
|
+
"reported_as": "no-restricted-globals"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"reference": "useTerpClient() + unwrap from @terp/react-core for request/response; useRealtimeChannel() from @terp/react-core for typed SSE/WebSocket subscriptions (one-use ticket minted through the generated client).",
|
|
16
|
+
"opt_out": "// terp-allow-generated-client-only: <reason>",
|
|
17
|
+
"runtime": {
|
|
18
|
+
"applicability": "not-applicable",
|
|
19
|
+
"rationale": "In the running bundle the sanctioned generated client is itself built on fetch, so egress-primitive use cannot be attributed to an app module from inside the app. One typed egress path is an authoring contract; network policy beyond it (CSP connect-src) is deployment configuration the framework does not own per module."
|
|
20
|
+
},
|
|
21
|
+
"restricted_surface": [
|
|
22
|
+
"restrictedGlobals",
|
|
23
|
+
"restrictedMemberCalls"
|
|
24
|
+
],
|
|
25
|
+
"corpus": true
|
|
26
|
+
}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/layout-contract",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "An opted-in app's archetype body slots accept only the contract's components",
|
|
5
|
-
"intent": "With a checked-in layout contract, each page archetype's body slot is constrained to the contract's sanctioned components, so screens stay structurally consistent and the failure message tells an agent exactly how to build the screen. Paired with the fail-closed runtime check on the rendered slot.",
|
|
6
|
-
"layer": "static-bespoke",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "terp/layout-contract",
|
|
12
|
-
"reported_as": "terp/layout-contract"
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"kind": "runtime",
|
|
16
|
-
"tool": "@terp/react-core",
|
|
17
|
-
"ref": "verifySlotChildren"
|
|
18
|
-
}
|
|
19
|
-
],
|
|
20
|
-
"opt_out": "// terp-allow-layout-contract: <reason>",
|
|
21
|
-
"reference": "frontend/layout-contract.json + the layoutContract bootstrap option (ADR 0079); verifySlotChildren in @terp/react-core is the runtime DOM check.",
|
|
22
|
-
"runtime": {
|
|
23
|
-
"applicability": "required"
|
|
24
|
-
},
|
|
25
|
-
"corpus": true
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/layout-contract",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "An opted-in app's archetype body slots accept only the contract's components",
|
|
5
|
+
"intent": "With a checked-in layout contract, each page archetype's body slot is constrained to the contract's sanctioned components, so screens stay structurally consistent and the failure message tells an agent exactly how to build the screen. Paired with the fail-closed runtime check on the rendered slot.",
|
|
6
|
+
"layer": "static-bespoke",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "terp/layout-contract",
|
|
12
|
+
"reported_as": "terp/layout-contract"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"kind": "runtime",
|
|
16
|
+
"tool": "@terp/react-core",
|
|
17
|
+
"ref": "verifySlotChildren"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"opt_out": "// terp-allow-layout-contract: <reason>",
|
|
21
|
+
"reference": "frontend/layout-contract.json + the layoutContract bootstrap option (ADR 0079); verifySlotChildren in @terp/react-core is the runtime DOM check.",
|
|
22
|
+
"runtime": {
|
|
23
|
+
"applicability": "required"
|
|
24
|
+
},
|
|
25
|
+
"corpus": true
|
|
26
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-cross-module-imports",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "An app module never imports a sibling module",
|
|
5
|
-
"intent": "Modules couple only through the platform packages and their own files. A sibling import — static, dynamic import(), relative or via the app alias — creates hidden coupling that breaks module isolation and independent evolution.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "terp/no-cross-module-imports",
|
|
12
|
-
"reported_as": "terp/no-cross-module-imports"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"opt_out": "// terp-allow-no-cross-module-imports: <reason>",
|
|
16
|
-
"runtime": {
|
|
17
|
-
"applicability": "not-applicable",
|
|
18
|
-
"rationale": "Module independence is an import-graph property of the source tree; the bundler merges every module into one dependency graph, after which a cross-module edge is indistinguishable from composition."
|
|
19
|
-
},
|
|
20
|
-
"corpus": true
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-cross-module-imports",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "An app module never imports a sibling module",
|
|
5
|
+
"intent": "Modules couple only through the platform packages and their own files. A sibling import — static, dynamic import(), relative or via the app alias — creates hidden coupling that breaks module isolation and independent evolution.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "terp/no-cross-module-imports",
|
|
12
|
+
"reported_as": "terp/no-cross-module-imports"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"opt_out": "// terp-allow-no-cross-module-imports: <reason>",
|
|
16
|
+
"runtime": {
|
|
17
|
+
"applicability": "not-applicable",
|
|
18
|
+
"rationale": "Module independence is an import-graph property of the source tree; the bundler merges every module into one dependency graph, after which a cross-module edge is indistinguishable from composition."
|
|
19
|
+
},
|
|
20
|
+
"corpus": true
|
|
21
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-deep-imports",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "App modules import platform packages from the root only",
|
|
5
|
-
"intent": "A deep import into a platform package's internals couples the app to files that are free to move; the package root is the published, stable surface. The refused path segments are declared in restricted-surface.json (deepImportPathSegments).",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "BOUNDARY_SPEC.internalImportPatterns",
|
|
12
|
-
"reported_as": "no-restricted-imports"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"reference": "@terp/*/src/* and @terp/*/dist/* imports are refused; import from the @terp/* package root.",
|
|
16
|
-
"opt_out": "// terp-allow-no-deep-imports: <reason>",
|
|
17
|
-
"runtime": {
|
|
18
|
-
"applicability": "not-applicable",
|
|
19
|
-
"rationale": "Package-boundary form: the bundler resolves and inlines whatever was imported, and the built artifact retains no distinction between a root import and a deep one."
|
|
20
|
-
},
|
|
21
|
-
"restricted_surface": [
|
|
22
|
-
"deepImportPathSegments"
|
|
23
|
-
],
|
|
24
|
-
"corpus": true
|
|
25
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-deep-imports",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "App modules import platform packages from the root only",
|
|
5
|
+
"intent": "A deep import into a platform package's internals couples the app to files that are free to move; the package root is the published, stable surface. The refused path segments are declared in restricted-surface.json (deepImportPathSegments).",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "BOUNDARY_SPEC.internalImportPatterns",
|
|
12
|
+
"reported_as": "no-restricted-imports"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"reference": "@terp/*/src/* and @terp/*/dist/* imports are refused; import from the @terp/* package root.",
|
|
16
|
+
"opt_out": "// terp-allow-no-deep-imports: <reason>",
|
|
17
|
+
"runtime": {
|
|
18
|
+
"applicability": "not-applicable",
|
|
19
|
+
"rationale": "Package-boundary form: the bundler resolves and inlines whatever was imported, and the built artifact retains no distinction between a root import and a deep one."
|
|
20
|
+
},
|
|
21
|
+
"restricted_surface": [
|
|
22
|
+
"deepImportPathSegments"
|
|
23
|
+
],
|
|
24
|
+
"corpus": true
|
|
25
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-dom-html-injection",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "DOM HTML-injection sinks are refused in app modules",
|
|
5
|
-
"intent": "dangerouslySetInnerHTML, innerHTML/outerHTML assignment, insertAdjacentHTML and document.write inject markup that bypasses the framework's output escaping — the canonical XSS sink. Rich text renders through the stack's sanctioned rich-text component instead.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "terp/no-dom-html-injection",
|
|
12
|
-
"reported_as": "terp/no-dom-html-injection"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"reference": "The Markdown component from @terp/react-core for rich text.",
|
|
16
|
-
"opt_out": "// terp-allow-no-dom-html-injection: <reason>",
|
|
17
|
-
"runtime": {
|
|
18
|
-
"applicability": "not-applicable",
|
|
19
|
-
"rationale": "The sinks are platform primitives on every element; React's default output escaping is the ambient constructive protection and the sanctioned Markdown component sanitises rich text. A runtime hook over every element's HTML mutation is not a seam react-core owns or could make sound -- vendored code legitimately uses the same primitives."
|
|
20
|
-
},
|
|
21
|
-
"corpus": true
|
|
22
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-dom-html-injection",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "DOM HTML-injection sinks are refused in app modules",
|
|
5
|
+
"intent": "dangerouslySetInnerHTML, innerHTML/outerHTML assignment, insertAdjacentHTML and document.write inject markup that bypasses the framework's output escaping — the canonical XSS sink. Rich text renders through the stack's sanctioned rich-text component instead.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "terp/no-dom-html-injection",
|
|
12
|
+
"reported_as": "terp/no-dom-html-injection"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"reference": "The Markdown component from @terp/react-core for rich text.",
|
|
16
|
+
"opt_out": "// terp-allow-no-dom-html-injection: <reason>",
|
|
17
|
+
"runtime": {
|
|
18
|
+
"applicability": "not-applicable",
|
|
19
|
+
"rationale": "The sinks are platform primitives on every element; React's default output escaping is the ambient constructive protection and the sanctioned Markdown component sanitises rich text. A runtime hook over every element's HTML mutation is not a seam react-core owns or could make sound -- vendored code legitimately uses the same primitives."
|
|
20
|
+
},
|
|
21
|
+
"corpus": true
|
|
22
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-eval",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "eval() and new Function() are refused in app modules",
|
|
5
|
-
"intent": "Runtime code evaluation defeats every static guarantee the boundary provides and is a classic injection primitive. There is no sanctioned dynamic-code path in an app module.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "terp/no-eval",
|
|
12
|
-
"reported_as": "terp/no-eval"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"opt_out": "// terp-allow-no-eval: <reason>",
|
|
16
|
-
"runtime": {
|
|
17
|
-
"applicability": "not-applicable",
|
|
18
|
-
"rationale": "The prohibition is on authoring dynamic-code primitives in app modules \u2014 a source-form fact. In the running bundle the primitive itself is a platform global the framework cannot remove, and legitimately vendored code may reference it, so a runtime hook cannot attribute authorship to an app module. Deployment-level CSP can harden the served app, but it is deployment configuration, not a control this framework owns per rule."
|
|
19
|
-
},
|
|
20
|
-
"corpus": true
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-eval",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "eval() and new Function() are refused in app modules",
|
|
5
|
+
"intent": "Runtime code evaluation defeats every static guarantee the boundary provides and is a classic injection primitive. There is no sanctioned dynamic-code path in an app module.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "terp/no-eval",
|
|
12
|
+
"reported_as": "terp/no-eval"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"opt_out": "// terp-allow-no-eval: <reason>",
|
|
16
|
+
"runtime": {
|
|
17
|
+
"applicability": "not-applicable",
|
|
18
|
+
"rationale": "The prohibition is on authoring dynamic-code primitives in app modules \u2014 a source-form fact. In the running bundle the primitive itself is a platform global the framework cannot remove, and legitimately vendored code may reference it, so a runtime hook cannot attribute authorship to an app module. Deployment-level CSP can harden the served app, but it is deployment configuration, not a control this framework owns per rule."
|
|
19
|
+
},
|
|
20
|
+
"corpus": true
|
|
21
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-inline-styling",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "style and className attributes are refused in app modules",
|
|
5
|
-
"intent": "A style or className attribute is a side channel into hand-authored CSS that drifts per screen; styling flows from the app's design tokens and sanctioned layout primitives only. The refused attributes are declared in restricted-surface.json (restrictedAttributes).",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "BOUNDARY_SPEC.restrictedAttributes",
|
|
12
|
-
"reported_as": "no-restricted-syntax"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"reference": "Layout via Stack, DetailList and the page archetypes from @terp/react-core; theming via the app's token source.",
|
|
16
|
-
"opt_out": "// terp-allow-no-inline-styling: <reason>",
|
|
17
|
-
"runtime": {
|
|
18
|
-
"applicability": "not-applicable",
|
|
19
|
-
"rationale": "style/className are authoring-surface attributes: the token pipeline itself emits inline styles and class names into the built DOM, so their presence at runtime is legitimate and unattributable to app authorship."
|
|
20
|
-
},
|
|
21
|
-
"restricted_surface": [
|
|
22
|
-
"restrictedAttributes"
|
|
23
|
-
],
|
|
24
|
-
"corpus": true
|
|
25
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-inline-styling",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "style and className attributes are refused in app modules",
|
|
5
|
+
"intent": "A style or className attribute is a side channel into hand-authored CSS that drifts per screen; styling flows from the app's design tokens and sanctioned layout primitives only. The refused attributes are declared in restricted-surface.json (restrictedAttributes).",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "BOUNDARY_SPEC.restrictedAttributes",
|
|
12
|
+
"reported_as": "no-restricted-syntax"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"reference": "Layout via Stack, DetailList and the page archetypes from @terp/react-core; theming via the app's token source.",
|
|
16
|
+
"opt_out": "// terp-allow-no-inline-styling: <reason>",
|
|
17
|
+
"runtime": {
|
|
18
|
+
"applicability": "not-applicable",
|
|
19
|
+
"rationale": "style/className are authoring-surface attributes: the token pipeline itself emits inline styles and class names into the built DOM, so their presence at runtime is legitimate and unattributable to app authorship."
|
|
20
|
+
},
|
|
21
|
+
"restricted_surface": [
|
|
22
|
+
"restrictedAttributes"
|
|
23
|
+
],
|
|
24
|
+
"corpus": true
|
|
25
|
+
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-style-imports",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "Module-authored stylesheets are refused",
|
|
5
|
-
"intent": "Importing a stylesheet from an app module reintroduces per-screen CSS; theming flows from the app's token source only. The refused stylesheet extensions are declared in restricted-surface.json (styleImportExtensions).",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "BOUNDARY_SPEC.styleImportPatterns",
|
|
12
|
-
"reported_as": "no-restricted-imports"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"opt_out": "// terp-allow-no-style-imports: <reason>",
|
|
16
|
-
"runtime": {
|
|
17
|
-
"applicability": "not-applicable",
|
|
18
|
-
"rationale": "A stylesheet import is a build-graph edge; the bundler compiles it into the emitted CSS, after which module authorship does not exist."
|
|
19
|
-
},
|
|
20
|
-
"restricted_surface": [
|
|
21
|
-
"styleImportExtensions"
|
|
22
|
-
],
|
|
23
|
-
"corpus": true
|
|
24
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-style-imports",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "Module-authored stylesheets are refused",
|
|
5
|
+
"intent": "Importing a stylesheet from an app module reintroduces per-screen CSS; theming flows from the app's token source only. The refused stylesheet extensions are declared in restricted-surface.json (styleImportExtensions).",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "BOUNDARY_SPEC.styleImportPatterns",
|
|
12
|
+
"reported_as": "no-restricted-imports"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"opt_out": "// terp-allow-no-style-imports: <reason>",
|
|
16
|
+
"runtime": {
|
|
17
|
+
"applicability": "not-applicable",
|
|
18
|
+
"rationale": "A stylesheet import is a build-graph edge; the bundler compiles it into the emitted CSS, after which module authorship does not exist."
|
|
19
|
+
},
|
|
20
|
+
"restricted_surface": [
|
|
21
|
+
"styleImportExtensions"
|
|
22
|
+
],
|
|
23
|
+
"corpus": true
|
|
24
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-unsafe-href",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "javascript: URLs are refused in app modules",
|
|
5
|
-
"intent": "A javascript: href executes script on click \u2014 an XSS vector that survives the framework's attribute escaping. Links carry http(s), mailto, tel or in-app router paths only.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "terp/no-unsafe-href",
|
|
12
|
-
"reported_as": "terp/no-unsafe-href"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"opt_out": "// terp-allow-no-unsafe-href: <reason>",
|
|
16
|
-
"runtime": {
|
|
17
|
-
"applicability": "not-applicable",
|
|
18
|
-
"rationale": "The refusal is of authoring javascript: URLs in source. Data-driven links are the sanctioned components' own concern (the Markdown component strips unsafe protocols at render -- its control, not this rule's), and raw anchors are refused wholesale in app modules anyway."
|
|
19
|
-
},
|
|
20
|
-
"corpus": true
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-unsafe-href",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "javascript: URLs are refused in app modules",
|
|
5
|
+
"intent": "A javascript: href executes script on click \u2014 an XSS vector that survives the framework's attribute escaping. Links carry http(s), mailto, tel or in-app router paths only.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "terp/no-unsafe-href",
|
|
12
|
+
"reported_as": "terp/no-unsafe-href"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"opt_out": "// terp-allow-no-unsafe-href: <reason>",
|
|
16
|
+
"runtime": {
|
|
17
|
+
"applicability": "not-applicable",
|
|
18
|
+
"rationale": "The refusal is of authoring javascript: URLs in source. Data-driven links are the sanctioned components' own concern (the Markdown component strips unsafe protocols at render -- its control, not this rule's), and raw anchors are refused wholesale in app modules anyway."
|
|
19
|
+
},
|
|
20
|
+
"corpus": true
|
|
21
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/no-unsafe-target-blank",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "A static target=\"_blank\" link declares rel=\"noopener\"",
|
|
5
|
-
"intent": "Without rel=noopener the opened page holds a window.opener reference to the app \u2014 the reverse-tabnabbing primitive. The rule enforces the safe default on every statically-authored external link.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "terp/no-unsafe-target-blank",
|
|
12
|
-
"reported_as": "terp/no-unsafe-target-blank"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"opt_out": "// terp-allow-no-unsafe-target-blank: <reason>",
|
|
16
|
-
"runtime": {
|
|
17
|
-
"applicability": "not-applicable",
|
|
18
|
-
"rationale": "An authored static target=_blank without rel is a source form; the residual risk it addresses is legacy-engine reverse-tabnabbing, fixable only where the anchor is written. Modern engines default to noopener behaviour, and raw anchors are refused wholesale in app modules regardless."
|
|
19
|
-
},
|
|
20
|
-
"corpus": true
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/no-unsafe-target-blank",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "A static target=\"_blank\" link declares rel=\"noopener\"",
|
|
5
|
+
"intent": "Without rel=noopener the opened page holds a window.opener reference to the app \u2014 the reverse-tabnabbing primitive. The rule enforces the safe default on every statically-authored external link.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "terp/no-unsafe-target-blank",
|
|
12
|
+
"reported_as": "terp/no-unsafe-target-blank"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"opt_out": "// terp-allow-no-unsafe-target-blank: <reason>",
|
|
16
|
+
"runtime": {
|
|
17
|
+
"applicability": "not-applicable",
|
|
18
|
+
"rationale": "An authored static target=_blank without rel is a source form; the residual risk it addresses is legacy-engine reverse-tabnabbing, fixable only where the anchor is written. Modern engines default to noopener behaviour, and raw anchors are refused wholesale in app modules regardless."
|
|
19
|
+
},
|
|
20
|
+
"corpus": true
|
|
21
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/router-links",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "In-app links go through the router, never a raw anchor",
|
|
5
|
-
"intent": "A raw <a href=\"/...\"> forces a full reload and skips the role-aware route guard; in-app navigation uses the stack's router-integrated link. External https:// anchors stay allowed.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "BOUNDARY_SPEC.restrictInAppAnchors",
|
|
12
|
-
"reported_as": "no-restricted-syntax"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"reference": "Link from @terp/react-core (router-integrated, role-aware).",
|
|
16
|
-
"opt_out": "// terp-allow-router-links: <reason>",
|
|
17
|
-
"runtime": {
|
|
18
|
-
"applicability": "not-applicable",
|
|
19
|
-
"rationale": "In the rendered DOM the router's own Link IS an anchor -- raw-anchor authorship is only visible in source, so no DOM check can distinguish a sanctioned link from a hand-written one."
|
|
20
|
-
},
|
|
21
|
-
"corpus": true
|
|
22
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/router-links",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "In-app links go through the router, never a raw anchor",
|
|
5
|
+
"intent": "A raw <a href=\"/...\"> forces a full reload and skips the role-aware route guard; in-app navigation uses the stack's router-integrated link. External https:// anchors stay allowed.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "BOUNDARY_SPEC.restrictInAppAnchors",
|
|
12
|
+
"reported_as": "no-restricted-syntax"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"reference": "Link from @terp/react-core (router-integrated, role-aware).",
|
|
16
|
+
"opt_out": "// terp-allow-router-links: <reason>",
|
|
17
|
+
"runtime": {
|
|
18
|
+
"applicability": "not-applicable",
|
|
19
|
+
"rationale": "In the rendered DOM the router's own Link IS an anchor -- raw-anchor authorship is only visible in source, so no DOM check can distinguish a sanctioned link from a hand-written one."
|
|
20
|
+
},
|
|
21
|
+
"corpus": true
|
|
22
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "frontend/token-styled-elements",
|
|
3
|
-
"surface": "frontend",
|
|
4
|
-
"title": "Raw interactive/structural HTML elements are refused in app modules",
|
|
5
|
-
"intent": "A raw <button>/<input>/<select>/<textarea>/<table>/<dialog>/<form> bypasses the app's sanctioned, token-styled primitive surface (accessible and theme-consistent by construction). The refused elements are declared in restricted-surface.json (restrictedElements); each has a sanctioned replacement in the stack's component surface, and the violation message names it.",
|
|
6
|
-
"layer": "static-portable",
|
|
7
|
-
"enforcement": [
|
|
8
|
-
{
|
|
9
|
-
"kind": "build-time",
|
|
10
|
-
"tool": "@terp/eslint-boundaries",
|
|
11
|
-
"ref": "BOUNDARY_SPEC.restrictedElements",
|
|
12
|
-
"reported_as": "no-restricted-syntax"
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"reference": "Button, Input, Select, Textarea, DataView, ConfirmDialog and Stack as=\"form\" from @terp/react-core (BOUNDARY_SPEC.restrictedElements maps each element to its replacement).",
|
|
16
|
-
"opt_out": "// terp-allow-token-styled-elements: <reason>",
|
|
17
|
-
"runtime": {
|
|
18
|
-
"applicability": "not-applicable",
|
|
19
|
-
"rationale": "The sanctioned components themselves render the raw elements into the built DOM -- every button on screen is legitimate output of Button. Compilation erases which JSX authored a node, and third-party components legitimately render the same primitives, so a DOM scan cannot soundly attribute a raw element to app authorship (unlike the layout contract's slot check, which verifies the identity of sanctioned components at one owned seam)."
|
|
20
|
-
},
|
|
21
|
-
"restricted_surface": [
|
|
22
|
-
"restrictedElements"
|
|
23
|
-
],
|
|
24
|
-
"corpus": true
|
|
25
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend/token-styled-elements",
|
|
3
|
+
"surface": "frontend",
|
|
4
|
+
"title": "Raw interactive/structural HTML elements are refused in app modules",
|
|
5
|
+
"intent": "A raw <button>/<input>/<select>/<textarea>/<table>/<dialog>/<form> bypasses the app's sanctioned, token-styled primitive surface (accessible and theme-consistent by construction). The refused elements are declared in restricted-surface.json (restrictedElements); each has a sanctioned replacement in the stack's component surface, and the violation message names it.",
|
|
6
|
+
"layer": "static-portable",
|
|
7
|
+
"enforcement": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "build-time",
|
|
10
|
+
"tool": "@terp/eslint-boundaries",
|
|
11
|
+
"ref": "BOUNDARY_SPEC.restrictedElements",
|
|
12
|
+
"reported_as": "no-restricted-syntax"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"reference": "Button, Input, Select, Textarea, DataView, ConfirmDialog and Stack as=\"form\" from @terp/react-core (BOUNDARY_SPEC.restrictedElements maps each element to its replacement).",
|
|
16
|
+
"opt_out": "// terp-allow-token-styled-elements: <reason>",
|
|
17
|
+
"runtime": {
|
|
18
|
+
"applicability": "not-applicable",
|
|
19
|
+
"rationale": "The sanctioned components themselves render the raw elements into the built DOM -- every button on screen is legitimate output of Button. Compilation erases which JSX authored a node, and third-party components legitimately render the same primitives, so a DOM scan cannot soundly attribute a raw element to app authorship (unlike the layout contract's slot check, which verifies the identity of sanctioned components at one owned seam)."
|
|
20
|
+
},
|
|
21
|
+
"restricted_surface": [
|
|
22
|
+
"restrictedElements"
|
|
23
|
+
],
|
|
24
|
+
"corpus": true
|
|
25
|
+
}
|