From c1594dba2fed54e9aee60a46858fc9d89940bdba Mon Sep 17 00:00:00 2001 From: Actual Operator Date: Wed, 1 Jul 2026 04:27:08 +0000 Subject: [PATCH] Sync context files with ADRs - Update .actual/rules/cross-cutting-test-classes-organize-d158.md (claude) - Update .actual/rules/cross-cutting-error-response-json-c4e2.md (claude) - Update .actual/rules/cross-cutting-test-methods-use-27a4.md (claude) - Update .actual/rules/cross-cutting-error-response-body-f91a.md (claude) - Update .actual/rules/cross-cutting-custom-exception-bitwardenerror-198d.md (claude) - Update .actual/rules/cross-cutting-http-error-response-b6ac.md (claude) - Update .actual/rules/cross-cutting-libraries-provide-hooks-8771.md (claude) - Update .actual/rules/cross-cutting-library-error-logging-722f.md (claude) - Update .actual/rules/cross-cutting-kotlin-network-libraries-a59d.md (claude) - Update .actual/rules/cross-cutting-typescript-libraries-use-0a85.md (claude) - Update .actual/rules/cross-cutting-error-log-entries-b607.md (claude) - Update .actual/rules/cross-cutting-library-modules-use-2f7e.md (claude) - Update .actual/rules/cross-cutting-tests-use-mock-0deb.md (claude) - Update .actual/rules/cross-cutting-test-classes-follow-9b1c.md (claude) - Update .actual/rules/cross-cutting-extension-functions-that-9c9d.md (claude) - Update .actual/rules/cross-cutting-when-type-discriminators-5dab.md (claude) - Update .actual/rules/cross-cutting-serialization-tests-use-40e0.md (claude) - Update .actual/rules/cross-cutting-custom-kotlinx-serialization-7733.md (claude) - Update .actual/rules/cross-cutting-tests-use-buildjsonobject-c361.md (claude) - Update .actual/rules/cross-cutting-test-methods-verifying-597c.md (claude) - Update .actual/rules/cross-cutting-serialization-tests-verify-8748.md (claude) - Update .actual/rules/cross-cutting-json-object-construction-6557.md (claude) - Update .actual/rules/cross-cutting-test-assertions-verifying-cd9f.md (claude) - Update .actual/rules/cross-cutting-viewmodels-inject-savedstatehandle-66c4.md (claude) - Update .actual/rules/cross-cutting-dialog-loading-states-c091.md (claude) - Update .actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-3cae.md (claude) - Update .actual/rules/cross-cutting-asynchronous-operations-execute-34bb.md (claude) - Update .actual/rules/cross-cutting-state-classes-implemented-3cf8.md (claude) - Update .actual/rules/cross-cutting-state-updates-use-2449.md (claude) - Update .actual/rules/cross-cutting-viewmodels-use-mutablestateflow-8c03.md (claude) - Update .actual/rules/cross-cutting-viewmodels-annotated-hiltviewmodel-b639.md (claude) - Update .actual/rules/cross-cutting-composable-functions-use-f5e4.md (claude) - Update .actual/rules/cross-cutting-handler-screen-components-27e5.md (claude) - Update .actual/rules/cross-cutting-composable-files-import-341a.md (claude) - Update .actual/rules/cross-cutting-composable-functions-use-42ea.md (claude) - Update .actual/rules/cross-cutting-screen-level-implementations-c0e0.md (claude) - Update .actual/rules/cross-cutting-component-functions-that-68f3.md (claude) - Update .actual/rules/cross-cutting-composables-use-columnscope-4c90.md (claude) - Update .actual/rules/cross-cutting-navigation-lifecycle-events-3457.md (claude) - Update .actual/rules/cross-cutting-composables-use-androidx-4aea.md (claude) - Update .actual/rules/cross-cutting-screen-implementations-separate-575c.md (claude) - Update .actual/rules/cross-cutting-composable-functions-integrate-9d19.md (claude) - Update .actual/rules/cross-cutting-screen-composables-use-3522.md (claude) - Update .actual/rules/cross-cutting-screen-implementations-use-73df.md (claude) - Update .actual/rules/cross-cutting-viewmodels-inject-multiple-c778.md (claude) - Update .actual/rules/cross-cutting-viewmodels-handling-external-c129.md (claude) - Update .actual/rules/cross-cutting-intent-processing-logic-1ad0.md (claude) - Update .actual/rules/cross-cutting-public-action-contracts-270f.md (claude) - Update .actual/rules/cross-cutting-viewmodels-public-boundaries-67b3.md (claude) - Update .actual/rules/cross-cutting-viewmodels-handling-android-4582.md (claude) - Update .actual/rules/cross-cutting-implementations-extend-error-dbb8.md (claude) - Update .actual/rules/cross-cutting-server-implementations-use-4884.md (claude) - Update .actual/rules/cross-cutting-tool-error-logs-faca.md (claude) - Update .actual/rules/cross-cutting-mcp-servers-import-394d.md (claude) - Update .actual/rules/cross-cutting-fatal-server-errors-5945.md (claude) - Update .actual/rules/cross-cutting-mcp-server-implementations-aae0.md (claude) - Update .actual/rules/cross-cutting-scripts-combine-get-4258.md (claude) - Update .actual/rules/cross-cutting-scripts-use-direct-56b5.md (claude) - Update .actual/rules/cross-cutting-nested-field-access-e0d3.md (claude) - Update .actual/rules/cross-cutting-scripts-provide-appropriate-5bf4.md (claude) - Update .actual/rules/cross-cutting-integration-test-scripts-537e.md (claude) - Update .actual/rules/cross-cutting-implementations-extend-console-470c.md (claude) - Update .actual/rules/cross-cutting-error-messages-include-a9af.md (claude) - Update .actual/rules/cross-cutting-tool-lookup-operations-3695.md (claude) - Update .actual/rules/cross-cutting-error-logging-occur-5985.md (claude) - Update .actual/rules/cross-cutting-fatal-server-level-bc5d.md (claude) - Update .actual/rules/cross-cutting-tool-execution-errors-9c42.md (claude) - Update .actual/rules/cross-cutting-integration-components-separate-dbfa.md (claude) - Update .actual/rules/cross-cutting-type-definitions-modelcontextprotocol-3508.md (claude) - Update .actual/rules/cross-cutting-integration-servers-use-a61c.md (claude) - Update .actual/rules/cross-cutting-error-handling-distinguish-d0fc.md (claude) - Update .actual/rules/cross-cutting-tool-based-integrations-2f80.md (claude) - Update .actual/rules/cross-cutting-server-instances-declare-2d8f.md (claude) - Update .actual/rules/cross-cutting-real-time-integration-d898.md (claude) - Update .actual/rules/cross-cutting-tool-implementations-modularized-ceec.md (claude) - Update .actual/rules/cross-cutting-validation-utilities-separated-c0da.md (claude) - Update .actual/rules/cross-cutting-tool-lookup-use-e58a.md (claude) - Update .actual/rules/cross-cutting-fatal-errors-logged-0e95.md (claude) - Update .actual/rules/cross-cutting-tool-errors-logged-54a4.md (claude) - Update .actual/rules/cross-cutting-type-definitions-imported-e555.md (claude) - Update .actual/rules/cross-cutting-stdio-transport-imported-10ae.md (claude) - Update .actual/rules/cross-cutting-server-initialization-declare-ebc9.md (claude) - Update .actual/rules/cross-cutting-mcp-server-implementations-42f6.md (claude) - Update .actual/rules/cross-cutting-dependency-injection-used-34c6.md (claude) - Update .actual/rules/cross-cutting-android-framework-components-b803.md (claude) - Update .actual/rules/cross-cutting-viewmodels-use-constructor-14cc.md (claude) - Update .actual/rules/cross-cutting-dependencies-injected-activities-aa04.md (claude) - Update .actual/rules/cross-cutting-application-class-use-ed5f.md (claude) - Update .actual/rules/cross-cutting-viewmodel-classes-annotated-37e9.md (claude) - Update .actual/rules/cross-cutting-android-activity-components-668b.md (claude) - Update .actual/rules/cross-cutting-activities-use-androidx-c392.md (claude) - Update .actual/rules/cross-cutting-activities-handling-system-ddfe.md (claude) - Update .actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-cc3e.md (claude) - Update .actual/rules/cross-cutting-activities-use-androidx-9fdc.md (claude) - Update .actual/rules/cross-cutting-activities-requiring-dependency-2c48.md (claude) - Update .actual/rules/cross-cutting-activity-implementations-override-4358.md (claude) - Update .actual/rules/cross-cutting-application-entry-points-442f.md (claude) - Update .actual/rules/cross-cutting-components-use-inject-243c.md (claude) - Update .actual/rules/cross-cutting-viewmodels-use-constructor-b4ab.md (claude) - Update .actual/rules/cross-cutting-activities-extending-componentactivity-7f82.md (claude) - Update .actual/rules/cross-cutting-dependencies-injected-android-77ba.md (claude) - Update .actual/rules/cross-cutting-application-class-use-7fe1.md (claude) - Update .actual/rules/cross-cutting-viewmodels-requiring-dependency-bc78.md (claude) - Update .actual/rules/cross-cutting-android-activities-requiring-ea4b.md (claude) - Update .actual/rules/cross-cutting-internal-functions-implement-3f09.md (claude) - Update .actual/rules/cross-cutting-scripts-that-invoke-3033.md (claude) - Update .actual/rules/cross-cutting-internal-that-process-c6b2.md (claude) - Update .actual/rules/cross-cutting-scripts-that-accept-b4a6.md (claude) - Update .actual/rules/cross-cutting-configuration-parsers-use-c30b.md (claude) - Update .actual/rules/cross-cutting-internal-scripts-that-a6ed.md (claude) - Update .actual/rules/cross-cutting-scripts-use-standard-13e8.md (claude) - Update .actual/rules/cross-cutting-label-manipulation-functions-1022.md (claude) - Update .actual/rules/cross-cutting-configuration-loading-functions-1ecc.md (claude) - Update .actual/rules/cross-cutting-functions-interacting-external-ad14.md (claude) - Update .actual/rules/cross-cutting-public-contract-functions-0f60.md (claude) - Update .actual/rules/cross-cutting-github-integration-scripts-f2fa.md (claude) - Update .actual/rules/cross-cutting-scripts-use-subprocess-0907.md (claude) - Update .actual/rules/cross-cutting-label-operations-use-2e0e.md (claude) - Update .actual/rules/cross-cutting-configuration-define-application-f12f.md (claude) - Update .actual/rules/cross-cutting-github-interactions-encapsulated-dcfc.md (claude) - Update .actual/rules/cross-cutting-scripts-implement-exception-39f9.md (claude) - Update .actual/rules/cross-cutting-label-assignment-logic-e610.md (claude) - Update .actual/rules/cross-cutting-automation-scripts-load-f44a.md (claude) - Update .actual/rules/cross-cutting-validation-schemas-include-3c4f.md (claude) - Update .actual/rules/cross-cutting-public-contracts-exported-2e18.md (claude) - Update .actual/rules/cross-cutting-tool-handlers-import-9bfd.md (claude) - Update .actual/rules/cross-cutting-validation-utilities-imported-0c4d.md (claude) - Update .actual/rules/cross-cutting-validation-schemas-use-9f64.md (claude) - Update .actual/rules/cross-cutting-tool-handlers-implemented-e293.md (claude) - Update .actual/rules/cross-cutting-public-tool-handlers-deff.md (claude) - Update .actual/rules/cross-cutting-application-specific-labels-53b2.md (claude) - Update .actual/rules/cross-cutting-label-operations-handle-1a7c.md (claude) - Update .actual/rules/cross-cutting-configuration-pattern-matching-2518.md (claude) - Update .actual/rules/cross-cutting-external-calls-add-5042.md (claude) - Update .actual/rules/cross-cutting-pattern-matching-against-b313.md (claude) - Update .actual/rules/cross-cutting-label-accumulation-use-6360.md (claude) - Update .actual/rules/cross-cutting-tool-modules-separate-8b2d.md (claude) - Update .actual/rules/cross-cutting-handler-functions-not-b9c3.md (claude) - Update .actual/rules/cross-cutting-handler-functions-use-5910.md (claude) - Update .actual/rules/cross-cutting-input-validation-zod-39c6.md (claude) - Update .actual/rules/cross-cutting-handler-functions-coordinate-0482.md (claude) - Update .actual/rules/cross-cutting-tool-implementations-export-cf91.md (claude) - Update .actual/rules/cross-cutting-use-alternative-collection-7913.md (claude) - Update .actual/rules/cross-cutting-avoid-manual-iteration-1ba7.md (claude) - Update .actual/rules/cross-cutting-predicate-functions-passed-fc06.md (claude) - Update .actual/rules/cross-cutting-use-set-add-a890.md (claude) - Update .actual/rules/cross-cutting-use-array-find-3f88.md (claude) - Update .actual/rules/cross-cutting-scripts-use-predicate-6be1.md (claude) - Update .actual/rules/cross-cutting-json-data-loading-4759.md (claude) - Update .actual/rules/cross-cutting-memory-data-access-7a73.md (claude) - Update .actual/rules/cross-cutting-python-automation-scripts-7c5d.md (claude) - Update .actual/rules/cross-cutting-file-system-operations-39de.md (claude) - Update .actual/rules/cross-cutting-test-specifications-typescript-ff88.md (claude) - Update .actual/rules/cross-cutting-additional-validation-constraints-be5d.md (claude) - Update .actual/rules/cross-cutting-validation-utilities-centralized-f02d.md (claude) - Update .actual/rules/cross-cutting-validation-schemas-define-a0dd.md (claude) - Update .actual/rules/cross-cutting-json-configuration-files-8d59.md (claude) - Update .actual/rules/cross-cutting-numeric-inputs-representing-2f96.md (claude) - Update .actual/rules/cross-cutting-xml-parsing-operations-dd22.md (claude) - Update .actual/rules/cross-cutting-public-endpoints-tool-48f1.md (claude) - Update .actual/rules/cross-cutting-use-custom-validation-0705.md (claude) - Update .actual/rules/cross-cutting-optional-parameters-declare-567e.md (claude) - Update .actual/rules/cross-cutting-numeric-inputs-include-ae1a.md (claude) - Update .actual/rules/cross-cutting-validation-failures-result-13ac.md (claude) - Update .actual/rules/cross-cutting-schema-definitions-specify-ed0c.md (claude) - Update .actual/rules/cross-cutting-input-validation-occur-478e.md (claude) - Update .actual/rules/cross-cutting-public-endpoints-that-0acc.md (claude) - Update .actual/rules/cross-cutting-boolean-flag-parameters-2f3c.md (claude) - Update .actual/rules/cross-cutting-tool-implementations-import-f8f4.md (claude) - Update .actual/rules/cross-cutting-optional-parameters-declare-8bf8.md (claude) - Update .actual/rules/cross-cutting-timing-parameters-waitseconds-72ef.md (claude) - Update .actual/rules/cross-cutting-numeric-coordinate-parameters-2d66.md (claude) - Update .actual/rules/cross-cutting-tool-handlers-that-5b55.md (claude) - Update .actual/rules/cross-cutting-tests-use-mocking-4a66.md (claude) - Update .actual/rules/cross-cutting-typescript-tests-organize-9c5a.md (claude) - Update .actual/rules/cross-cutting-python-tests-use-cfac.md (claude) - Update .actual/rules/cross-cutting-test-method-names-f006.md (claude) - Update .actual/rules/cross-cutting-python-test-classes-6e3e.md (claude) - Update .actual/rules/cross-cutting-typescript-test-files-3a62.md (claude) - Update .actual/rules/cross-cutting-python-test-files-de0b.md (claude) - Update .actual/rules/cross-cutting-test-descriptions-use-18ee.md (claude) - Update .actual/rules/cross-cutting-tests-verify-both-6b75.md (claude) - Update .actual/rules/cross-cutting-test-fixtures-organized-85db.md (claude) - Update .actual/rules/cross-cutting-test-classes-implement-772c.md (claude) - Update .actual/rules/cross-cutting-typescript-test-files-dbef.md (claude) - Update .actual/rules/cross-cutting-python-test-methods-8229.md (claude) - Update .actual/rules/cross-cutting-typescript-test-modules-d6b5.md (claude) - Update .actual/rules/cross-cutting-python-test-modules-e4ca.md (claude) - Update .actual/rules/cross-cutting-tests-suppress-stdout-270e.md (claude) - Update .actual/rules/cross-cutting-test-fixtures-use-0e93.md (claude) - Update .actual/rules/cross-cutting-test-methods-include-02ab.md (claude) - Update .actual/rules/cross-cutting-public-test-contracts-600b.md (claude) - Update .actual/rules/cross-cutting-test-classes-implement-dead.md (claude) - Update .actual/rules/cross-cutting-test-classes-implement-2b73.md (claude) - Update .actual/rules/cross-cutting-test-classes-inherit-bf00.md (claude) - Update CLAUDE.md (claude) - Update AGENTS.md (agents) - Update docs/adr/d158cb0f-6daf-4b88-89e4-957f2b1b8826-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-classes-organize.md (docs) - Update docs/adr/c4e21335-6ee6-4833-9d24-9a8225827ff8-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-json.md (docs) - Update docs/adr/27a4b14f-c454-4d0a-9fc6-5fee8f57ce91-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-methods-use.md (docs) - Update docs/adr/f91ae19b-2748-445b-8617-0fb6a06e5b19-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-body.md (docs) - Update docs/adr/198d8e26-bd59-4514-bbb8-36b222726207-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-custom-exception-bitwardenerror.md (docs) - Update docs/adr/b6ac444b-c292-4cbc-90bc-80331575d6a6-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-http-error-response.md (docs) - Update docs/adr/87712dbb-078d-457f-a0d9-2400b5d8b012-standardize-console-error-and-response-error-for-error-logging-in-libraries-libraries-provide-hooks.md (docs) - Update docs/adr/722f54e6-84df-4098-bb25-b1a404fd7445-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-error-logging.md (docs) - Update docs/adr/a59d9d80-8ebf-4f68-9ead-eccacbe96b50-standardize-console-error-and-response-error-for-error-logging-in-libraries-kotlin-network-libraries.md (docs) - Update docs/adr/0a858504-83de-443b-b3d8-56bb1f18bb5a-standardize-console-error-and-response-error-for-error-logging-in-libraries-typescript-libraries-use.md (docs) - Update docs/adr/b607cb14-16bb-49df-a9c8-04f43e0c585b-standardize-console-error-and-response-error-for-error-logging-in-libraries-error-log-entries.md (docs) - Update docs/adr/2f7ee62b-4dfb-485a-8c08-8718131a2325-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-modules-use.md (docs) - Update docs/adr/0deb24db-6744-474e-86e4-0084c8180782-standardize-kotlinx-serialization-json-testing-with-type-discriminators-tests-use-mock.md (docs) - Update docs/adr/9b1cd432-f6b2-4d64-949d-1ed6f8997b22-standardize-kotlinx-serialization-json-testing-with-type-discriminators-test-classes-follow.md (docs) - Update docs/adr/9c9dd63b-7128-418f-a8e3-558cd55fddac-standardize-kotlinx-serialization-json-testing-with-type-discriminators-extension-functions-that.md (docs) - Update docs/adr/5dab80b0-9a3b-4743-8d55-84d6db3f8171-standardize-kotlinx-serialization-json-testing-with-type-discriminators-when-type-discriminators.md (docs) - Update docs/adr/40e0fe78-854d-4145-942b-c15fcae948ee-standardize-kotlinx-serialization-json-testing-with-type-discriminators-serialization-tests-use.md (docs) - Update docs/adr/77336862-f4d2-43f8-9f85-1649fcc3fc0c-standardize-kotlinx-serialization-json-testing-with-type-discriminators-custom-kotlinx-serialization.md (docs) - Update docs/adr/c36190bb-c866-44bd-a3af-c6a04e54d73b-use-json-builder-dsl-for-test-assertion-construction-tests-use-buildjsonobject.md (docs) - Update docs/adr/597c203b-68e5-47e1-b387-760021689b99-use-json-builder-dsl-for-test-assertion-construction-test-methods-verifying.md (docs) - Update docs/adr/874842c0-a39c-4d3a-b1a9-4349607256d3-use-json-builder-dsl-for-test-assertion-construction-serialization-tests-verify.md (docs) - Update docs/adr/65578697-b9b2-469e-b60a-75d8f7d82639-use-json-builder-dsl-for-test-assertion-construction-json-object-construction.md (docs) - Update docs/adr/cd9fb085-7d4d-4567-9f79-0b0dfc05be78-use-json-builder-dsl-for-test-assertion-construction-test-assertions-verifying.md (docs) - Update docs/adr/66c4ea0f-5e64-4cdc-bb11-8ae3cdb5c69b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-inject-savedstatehandle.md (docs) - Update docs/adr/c091855f-fd5f-46da-b033-7a6ab3a1fa54-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-dialog-loading-states.md (docs) - Update docs/adr/3caee969-a463-4602-a10a-a9d0ac8725fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-extend-baseviewmodel.md (docs) - Update docs/adr/34bbb099-aca5-4383-ac43-e7fa38bf8036-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-asynchronous-operations-execute.md (docs) - Update docs/adr/3cf8eb73-bea4-4643-86bf-b694273ab96b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-classes-implemented.md (docs) - Update docs/adr/2449364d-4257-4659-b3a9-4e88ad892e92-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-updates-use.md (docs) - Update docs/adr/8c033a44-0889-415a-8770-e35d0d4c03fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-use-mutablestateflow.md (docs) - Update docs/adr/b6399a6b-ae13-419a-ab12-6bfe49660899-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-annotated-hiltviewmodel.md (docs) - Update docs/adr/f5e43e08-8bf6-4b41-a34c-4721ee14a1b4-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md (docs) - Update docs/adr/27e5a784-711c-42af-b6dd-7ab5561d68f1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-handler-screen-components.md (docs) - Update docs/adr/341a988b-b32d-469a-a0ff-70671c52b46d-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-files-import.md (docs) - Update docs/adr/42ea08ba-ec5f-4deb-a4f5-082aba434692-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md (docs) - Update docs/adr/c0e01dbb-c7d8-4249-9ff1-6b54930f33e1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-screen-level-implementations.md (docs) - Update docs/adr/68f32bb1-c4fa-4894-a34c-c2b358509119-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-component-functions-that.md (docs) - Update docs/adr/4c90fdd9-d9d1-4228-9ca7-c4e47c517fe1-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-columnscope.md (docs) - Update docs/adr/34575625-c418-4842-8fcc-12beb0210e02-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-navigation-lifecycle-events.md (docs) - Update docs/adr/4aea4cc3-aecc-4def-a941-be94472e80e2-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-androidx.md (docs) - Update docs/adr/575c687d-732e-4964-99df-666d2a785e8c-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-separate.md (docs) - Update docs/adr/9d193d2c-ca56-4e12-9dc7-0666fbb5267a-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composable-functions-integrate.md (docs) - Update docs/adr/3522412b-75d3-403a-b692-053f3c8cfd0e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-composables-use.md (docs) - Update docs/adr/73df07ab-a3ee-4ae4-95f3-55ea8d01548e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-use.md (docs) - Update docs/adr/c77883cd-f54d-461e-825b-f33537a65086-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-inject-multiple.md (docs) - Update docs/adr/c1294673-f723-4fa2-9d29-ed728b1b02f2-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-external.md (docs) - Update docs/adr/1ad0412a-5069-4826-818c-2d9c8afdc0df-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-intent-processing-logic.md (docs) - Update docs/adr/270f5ea8-6f63-45b7-b26b-02e89a5929ca-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-public-action-contracts.md (docs) - Update docs/adr/67b3466d-4c62-4a90-8600-c539cf78d7c4-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-public-boundaries.md (docs) - Update docs/adr/45829dc1-79d0-4b6b-b98f-10f9cf88e1bf-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-android.md (docs) - Update docs/adr/dbb825c6-c6c7-4a92-8d5a-239b88eff0bb-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-implementations-extend-error.md (docs) - Update docs/adr/48843ec7-e1ab-4e68-95a6-f2d29f81c835-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-server-implementations-use.md (docs) - Update docs/adr/facaccf3-6586-4106-b5ac-4ada57f5feb2-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-tool-error-logs.md (docs) - Update docs/adr/394dd45f-d4b2-4184-83e2-5fd2fdc2959f-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-servers-import.md (docs) - Update docs/adr/59455fca-b2b2-4ac4-b814-b47e9dc84402-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-fatal-server-errors.md (docs) - Update docs/adr/aae0f285-d3e2-4c79-90f6-2ba6356f3559-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-server-implementations.md (docs) - Update docs/adr/4258dbf5-ca5a-43b8-aec7-6ca64a00e937-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-combine-get.md (docs) - Update docs/adr/56b52c53-ab5b-4371-9e76-41f731828a0d-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-use-direct.md (docs) - Update docs/adr/e0d37356-1631-46f3-97d8-1f8d05fd6507-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-nested-field-access.md (docs) - Update docs/adr/5bf424b3-89eb-4096-8559-2239b4337494-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-provide-appropriate.md (docs) - Update docs/adr/537e96b2-a713-4732-bd41-e78399595757-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-integration-test-scripts.md (docs) - Update docs/adr/470c2bc4-87ff-4400-a07b-fb279d52be45-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-implementations-extend-console.md (docs) - Update docs/adr/a9af7708-c42b-43f6-b33a-c7922023a6a7-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-messages-include.md (docs) - Update docs/adr/369552b7-50d1-4a9f-967a-17aa9e99288f-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-lookup-operations.md (docs) - Update docs/adr/59851339-3655-43a8-8e80-a25247c1f58d-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-logging-occur.md (docs) - Update docs/adr/bc5d0ec4-e4fb-4c43-945a-977c37f92a37-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-fatal-server-level.md (docs) - Update docs/adr/9c42ab5a-68cb-49ad-862a-c6599f730ae4-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-execution-errors.md (docs) - Update docs/adr/dbfa248c-cae8-4b7a-86a3-b5500a8e6cee-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-components-separate.md (docs) - Update docs/adr/3508da20-cca1-4896-bb22-11b5c9bc8431-adopt-model-context-protocol-sdk-for-real-time-device-integration-type-definitions-modelcontextprotocol.md (docs) - Update docs/adr/a61ccece-339e-4912-9357-9ce009aa78df-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-servers-use.md (docs) - Update docs/adr/d0fc711e-daaf-43ac-8555-b20545adec9a-adopt-model-context-protocol-sdk-for-real-time-device-integration-error-handling-distinguish.md (docs) - Update docs/adr/2f80d513-9981-40a9-b1ad-18f2cd79a59b-adopt-model-context-protocol-sdk-for-real-time-device-integration-tool-based-integrations.md (docs) - Update docs/adr/2d8fc4df-c881-4439-990d-de74ed8e0868-adopt-model-context-protocol-sdk-for-real-time-device-integration-server-instances-declare.md (docs) - Update docs/adr/d89870be-79f5-4b57-9124-0ebfa63ccf07-adopt-model-context-protocol-sdk-for-real-time-device-integration-real-time-integration.md (docs) - Update docs/adr/ceec2cd4-0327-4e63-817b-921b9a4415da-adopt-model-context-protocol-sdk-for-android-device-integration-tool-implementations-modularized.md (docs) - Update docs/adr/c0da1b83-7641-4636-94f2-6b7299cbd587-adopt-model-context-protocol-sdk-for-android-device-integration-validation-utilities-separated.md (docs) - Update docs/adr/e58a0565-70ba-4773-89f2-1b12438a06f6-adopt-model-context-protocol-sdk-for-android-device-integration-tool-lookup-use.md (docs) - Update docs/adr/0e95ad4a-c8ed-42a9-af64-2737d2ce5b48-adopt-model-context-protocol-sdk-for-android-device-integration-fatal-errors-logged.md (docs) - Update docs/adr/54a455ad-a22f-44a9-89e7-ec0b36cddbae-adopt-model-context-protocol-sdk-for-android-device-integration-tool-errors-logged.md (docs) - Update docs/adr/e555e1eb-f5f2-4d66-ae3c-34b596cf39dc-adopt-model-context-protocol-sdk-for-android-device-integration-type-definitions-imported.md (docs) - Update docs/adr/10aeb070-b829-4092-aa40-68b28214a184-adopt-model-context-protocol-sdk-for-android-device-integration-stdio-transport-imported.md (docs) - Update docs/adr/ebc960ca-53bf-4ba9-9e24-ba3551bc90e3-adopt-model-context-protocol-sdk-for-android-device-integration-server-initialization-declare.md (docs) - Update docs/adr/42f674c8-a883-4f57-862a-e52d9c7e217a-adopt-model-context-protocol-sdk-for-android-device-integration-mcp-server-implementations.md (docs) - Update docs/adr/34c6892b-f9fa-4878-af0e-1f5462016952-adopt-hilt-dependency-injection-for-android-application-components-dependency-injection-used.md (docs) - Update docs/adr/b80305fd-3b3e-4655-b99a-700320564144-adopt-hilt-dependency-injection-for-android-application-components-android-framework-components.md (docs) - Update docs/adr/14cc0f9f-3d16-42a8-a5ef-ba36349bf042-adopt-hilt-dependency-injection-for-android-application-components-viewmodels-use-constructor.md (docs) - Update docs/adr/aa048d39-56ef-4832-9afe-beb1af3da70c-adopt-hilt-dependency-injection-for-android-application-components-dependencies-injected-activities.md (docs) - Update docs/adr/ed5f75c6-3d47-4881-8c46-b0fdccbde759-adopt-hilt-dependency-injection-for-android-application-components-application-class-use.md (docs) - Update docs/adr/37e9c4b9-11fc-4ddb-b1f8-9b38695ac6d0-adopt-hilt-dependency-injection-for-android-application-components-viewmodel-classes-annotated.md (docs) - Update docs/adr/668b18be-602f-4256-9ff1-cdb73bd4329a-adopt-hilt-dependency-injection-for-android-application-components-android-activity-components.md (docs) - Update docs/adr/c392ab05-f46c-43be-ac19-3bc5ce82c5e9-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md (docs) - Update docs/adr/ddfe2b69-49cf-4137-a3cf-95ba2ba77b05-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-handling-system.md (docs) - Update docs/adr/cc3efe3f-8dc4-4c51-99fb-c263092e61da-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-viewmodels-extend-baseviewmodel.md (docs) - Update docs/adr/9fdc35ed-c47b-4d09-8fd2-26a59f632114-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md (docs) - Update docs/adr/2c48296f-6f1b-484f-a794-3d4af770e641-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-requiring-dependency.md (docs) - Update docs/adr/43586977-155f-4fca-831c-ecd83c5f923f-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activity-implementations-override.md (docs) - Update docs/adr/442fb2a9-4d0e-4770-8b45-817b45829b74-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-application-entry-points.md (docs) - Update docs/adr/243cb603-fb8b-4db7-9f37-18ff5b0c99fe-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-components-use-inject.md (docs) - Update docs/adr/b4abce3f-6018-4a4b-a4ea-593f39ecd135-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-use-constructor.md (docs) - Update docs/adr/7f825e0c-d33b-43a0-ac74-3b7da9eefd92-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-activities-extending-componentactivity.md (docs) - Update docs/adr/77bab4bd-ee05-4209-af7b-5c3ed8a41b28-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-dependencies-injected-android.md (docs) - Update docs/adr/7fe11545-7b45-4360-a8bc-2d5c37949407-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-application-class-use.md (docs) - Update docs/adr/bc783d9d-976e-45d9-89e6-30ff07dcef64-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-requiring-dependency.md (docs) - Update docs/adr/ea4b543d-d0be-4462-9fa3-fa0b2f2fe57d-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-android-activities-requiring.md (docs) - Update docs/adr/3f096b2b-bdbd-4efe-8762-adb7c08e57f3-enforce-input-validation-for-internal-api-configuration-parsers-internal-functions-implement.md (docs) - Update docs/adr/30332d55-ad46-4c91-b4a2-e7c1a79f37a0-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-invoke.md (docs) - Update docs/adr/c6b2221d-a2a7-43d4-ac14-5a82f1353d03-enforce-input-validation-for-internal-api-configuration-parsers-internal-that-process.md (docs) - Update docs/adr/b4a63d5b-ac50-4f21-82dc-20bff4ab68fc-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-accept.md (docs) - Update docs/adr/c30bec5f-0d33-43b4-b42b-6cea3b39c20a-enforce-input-validation-for-internal-api-configuration-parsers-configuration-parsers-use.md (docs) - Update docs/adr/a6ed72bc-a5df-4c46-9d97-33bf7399d1ae-enforce-input-validation-for-internal-api-configuration-parsers-internal-scripts-that.md (docs) - Update docs/adr/13e82e07-7ed6-4df2-bd40-17cf7c29ed52-standardize-public-contract-functions-for-github-integration-automation-scripts-use-standard.md (docs) - Update docs/adr/1022ba63-742d-4d07-a9ca-ddf44b8b6f4a-standardize-public-contract-functions-for-github-integration-automation-label-manipulation-functions.md (docs) - Update docs/adr/1ecc1baf-393e-4a64-b544-82bf87d0fda2-standardize-public-contract-functions-for-github-integration-automation-configuration-loading-functions.md (docs) - Update docs/adr/ad140c48-3220-4bb1-9030-52b93713e782-standardize-public-contract-functions-for-github-integration-automation-functions-interacting-external.md (docs) - Update docs/adr/0f6063db-430f-4ec7-9201-c516c50a7078-standardize-public-contract-functions-for-github-integration-automation-public-contract-functions.md (docs) - Update docs/adr/f2faca50-9c9e-4ea3-95ac-c41b960a4059-standardize-public-contract-functions-for-github-integration-automation-github-integration-scripts.md (docs) - Update docs/adr/09073977-2366-4777-9cad-69ed4f5d103e-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-use-subprocess.md (docs) - Update docs/adr/2e0e51b9-ce85-493f-b4ee-423f63400418-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-operations-use.md (docs) - Update docs/adr/f12fda34-6c1a-45ce-937f-786fd0b3e6af-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-configuration-define-application.md (docs) - Update docs/adr/dcfc1578-9eef-45ea-aaab-245004231943-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-github-interactions-encapsulated.md (docs) - Update docs/adr/39f948de-aff4-47e6-95e7-0b3b2fb9fa9b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-implement-exception.md (docs) - Update docs/adr/e61011fa-9c21-47e2-bfeb-aa5f1be29b09-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-assignment-logic.md (docs) - Update docs/adr/f44a5164-24d3-4b66-8385-c0f71dfc3f0b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-automation-scripts-load.md (docs) - Update docs/adr/3c4f6334-326e-4af0-9e52-4693d07d104f-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-include.md (docs) - Update docs/adr/2e18e8d5-e460-4b7e-88a0-68d4f5d582b9-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-contracts-exported.md (docs) - Update docs/adr/9bfdca65-6800-424e-96c4-a54a6ae4d05d-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-import.md (docs) - Update docs/adr/0c4ddb3c-4f75-4172-a5dd-e6815bf1c6f1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-utilities-imported.md (docs) - Update docs/adr/9f645b4e-5542-4c5d-b627-a1751a2814c2-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-use.md (docs) - Update docs/adr/e293d8ea-c655-4557-92c6-da3bd24018b1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-implemented.md (docs) - Update docs/adr/deff453e-857e-46da-8a48-4d36fe3dbbd7-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-tool-handlers.md (docs) - Update docs/adr/53b25493-fa5e-4734-bb63-dbe38cf09832-standardize-set-based-label-management-for-external-client-boundaries-application-specific-labels.md (docs) - Update docs/adr/1a7cd7af-4fe9-4aee-afb0-4b1b9faa0cd4-standardize-set-based-label-management-for-external-client-boundaries-label-operations-handle.md (docs) - Update docs/adr/25181f2a-4b4a-421b-aef2-cbc5c9b1949e-standardize-set-based-label-management-for-external-client-boundaries-configuration-pattern-matching.md (docs) - Update docs/adr/50429da5-fe1f-4c10-8c86-b3226b013d16-standardize-set-based-label-management-for-external-client-boundaries-external-calls-add.md (docs) - Update docs/adr/b313895b-a93e-400c-8b22-620c2abad425-standardize-set-based-label-management-for-external-client-boundaries-pattern-matching-against.md (docs) - Update docs/adr/63609e18-cbc0-489d-8d3a-719e16b42c27-standardize-set-based-label-management-for-external-client-boundaries-label-accumulation-use.md (docs) - Update docs/adr/8b2d3bbd-e62e-41da-846f-2a7b570dfef8-adopt-async-handler-pattern-for-tool-operations-tool-modules-separate.md (docs) - Update docs/adr/b9c30d98-d40b-4301-9516-0097cc202473-adopt-async-handler-pattern-for-tool-operations-handler-functions-not.md (docs) - Update docs/adr/591073da-b16d-422c-a912-e14441d427d0-adopt-async-handler-pattern-for-tool-operations-handler-functions-use.md (docs) - Update docs/adr/39c6995b-ecab-4fe7-bea8-8c6d0f14d122-adopt-async-handler-pattern-for-tool-operations-input-validation-zod.md (docs) - Update docs/adr/0482e3b2-d96e-4410-a1b3-bfaff3c52773-adopt-async-handler-pattern-for-tool-operations-handler-functions-coordinate.md (docs) - Update docs/adr/cf91fbd7-c73a-4797-aee1-f3d03d7995d0-adopt-async-handler-pattern-for-tool-operations-tool-implementations-export.md (docs) - Update docs/adr/791389c7-39fe-4bfe-91d3-16d774336937-standardize-collection-find-pattern-for-in-memory-data-queries-use-alternative-collection.md (docs) - Update docs/adr/1ba7e0e8-f59d-4593-87e9-5ff0142cd818-standardize-collection-find-pattern-for-in-memory-data-queries-avoid-manual-iteration.md (docs) - Update docs/adr/fc062a0d-97da-44ac-9afe-094108c24e86-standardize-collection-find-pattern-for-in-memory-data-queries-predicate-functions-passed.md (docs) - Update docs/adr/a8900d19-7ca6-4686-8b55-c46711fdb7b8-standardize-collection-find-pattern-for-in-memory-data-queries-use-set-add.md (docs) - Update docs/adr/3f881fc6-f60d-48ce-b59c-a30ae2333de4-standardize-collection-find-pattern-for-in-memory-data-queries-use-array-find.md (docs) - Update docs/adr/6be14423-e197-4c2d-b1a4-364a8e436a4c-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-scripts-use-predicate.md (docs) - Update docs/adr/475964a8-a030-497f-8ce6-0cd39a8f5f03-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-json-data-loading.md (docs) - Update docs/adr/7a73643a-e287-430c-8108-7c1ab4049554-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-memory-data-access.md (docs) - Update docs/adr/7c5da194-79be-45e1-8dd2-fb82ce577b95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-python-automation-scripts.md (docs) - Update docs/adr/39de29ab-fa4d-44f9-be50-6358eb14ca5f-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-file-system-operations.md (docs) - Update docs/adr/ff882c06-6763-459c-a155-d6ee07394f95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-test-specifications-typescript.md (docs) - Update docs/adr/be5d07aa-1fe6-479b-af16-ce09f73ce4b6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-additional-validation-constraints.md (docs) - Update docs/adr/f02d043d-5823-4aeb-abfe-49a1db7895f6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-utilities-centralized.md (docs) - Update docs/adr/a0dd2b99-65aa-464c-a96f-8bf0ae9dcf2e-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-schemas-define.md (docs) - Update docs/adr/8d59b907-3996-4bdc-b0e6-38744356cc8f-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-json-configuration-files.md (docs) - Update docs/adr/2f964d88-ec51-4f7f-82a0-79bd1246932b-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-numeric-inputs-representing.md (docs) - Update docs/adr/dd22b744-04ad-4bef-826b-11857803deae-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-xml-parsing-operations.md (docs) - Update docs/adr/48f13c3a-a7cc-4d35-9b74-a5b204d2451d-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-public-endpoints-tool.md (docs) - Update docs/adr/0705eaa1-53bb-4b7d-85c5-442ae28e26ac-enforce-schema-based-input-validation-for-public-api-endpoints-use-custom-validation.md (docs) - Update docs/adr/567e6deb-4b37-4322-83a0-0d882acc8bb1-enforce-schema-based-input-validation-for-public-api-endpoints-optional-parameters-declare.md (docs) - Update docs/adr/ae1aaeb8-5a76-49e0-9577-9342abbb66e6-enforce-schema-based-input-validation-for-public-api-endpoints-numeric-inputs-include.md (docs) - Update docs/adr/13ace594-1891-4c1a-9207-864e5b351033-enforce-schema-based-input-validation-for-public-api-endpoints-validation-failures-result.md (docs) - Update docs/adr/ed0c7f79-7808-4d5a-a55b-ee6ba89ae4d1-enforce-schema-based-input-validation-for-public-api-endpoints-schema-definitions-specify.md (docs) - Update docs/adr/478e5fed-094b-4ef2-afc1-88f9aa6956a4-enforce-schema-based-input-validation-for-public-api-endpoints-input-validation-occur.md (docs) - Update docs/adr/0acc83c8-3c34-457a-9f19-eb7e32cc5e62-enforce-schema-based-input-validation-for-public-api-endpoints-public-endpoints-that.md (docs) - Update docs/adr/2f3cbae9-8b64-4724-9f11-bd00c23c4653-adopt-zod-schema-validation-for-tool-input-parameters-boolean-flag-parameters.md (docs) - Update docs/adr/f8f48f71-1510-4000-84be-9e9f3a16e0d9-adopt-zod-schema-validation-for-tool-input-parameters-tool-implementations-import.md (docs) - Update docs/adr/8bf8bb07-c7a7-4dc6-ae85-95c75ba9efd9-adopt-zod-schema-validation-for-tool-input-parameters-optional-parameters-declare.md (docs) - Update docs/adr/72ef156e-bd9d-4bad-87fc-e4ecb337b03e-adopt-zod-schema-validation-for-tool-input-parameters-timing-parameters-waitseconds.md (docs) - Update docs/adr/2d663395-aff0-4638-b8ed-0ade254d9757-adopt-zod-schema-validation-for-tool-input-parameters-numeric-coordinate-parameters.md (docs) - Update docs/adr/5b55513f-9bc8-4c6d-a31b-ccff626de6ca-adopt-zod-schema-validation-for-tool-input-parameters-tool-handlers-that.md (docs) - Update docs/adr/4a66eb0d-cd6e-4ff9-9141-68acdc062e52-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-tests-use-mocking.md (docs) - Update docs/adr/9c5ac160-2570-425b-91d6-cc6e790ed980-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-tests-organize.md (docs) - Update docs/adr/cfac6e70-958b-4189-8289-9daed54c616a-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-tests-use.md (docs) - Update docs/adr/f00636db-400f-40df-b081-6340fb4bdaa2-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-test-method-names.md (docs) - Update docs/adr/6e3e1b7f-9835-4724-84f8-c348d80e4aef-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-classes.md (docs) - Update docs/adr/3a62eecd-2793-47fe-8552-26629b08d87e-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-test-files.md (docs) - Update docs/adr/de0b6d27-1fae-4b8c-9a96-2aa4ce519252-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-files.md (docs) - Update docs/adr/18ee23ee-c8e0-463d-8d5a-4898ab14a630-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-descriptions-use.md (docs) - Update docs/adr/6b752b5a-f0df-4dce-ad73-38ba239f157b-adopt-unittest-and-vitest-as-standard-testing-frameworks-tests-verify-both.md (docs) - Update docs/adr/85dbd58a-e138-490a-ad09-20a2013a0794-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-fixtures-organized.md (docs) - Update docs/adr/772c14d7-cf35-44f6-8d91-f64c403cc25a-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-classes-implement.md (docs) - Update docs/adr/dbef69a5-6060-40bb-a8cd-ec32d52b7119-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-files.md (docs) - Update docs/adr/822904f8-d778-409d-ab3f-a2f2d3bfbac0-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-methods.md (docs) - Update docs/adr/d6b5a93c-a86e-48b5-ab0f-e66269b640ad-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-modules.md (docs) - Update docs/adr/e4caeb99-f530-4d0f-baad-a803acfbb9d2-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-modules.md (docs) - Update docs/adr/270e7300-2101-4791-bc58-0b9520e1145f-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-tests-suppress-stdout.md (docs) - Update docs/adr/0e93d40a-3759-43d3-ae74-525a465aa5a7-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-fixtures-use.md (docs) - Update docs/adr/02ab6269-efc6-43d8-8dab-11f6fad6e18c-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-methods-include.md (docs) - Update docs/adr/600b7997-bad6-44c8-8d7c-7eaee2b25819-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-public-test-contracts.md (docs) - Update docs/adr/deada6b8-5256-42f2-9304-3c6fcf5b13a9-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md (docs) - Update docs/adr/2b73f914-73c9-44f2-be05-509c1b7eb734-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md (docs) - Update docs/adr/bf0002f3-6984-42b2-aca2-730034c01e8b-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-inherit.md (docs) --- ...vities-extending-componentactivity-7f82.md | 37 +++++ ...cutting-activities-handling-system-ddfe.md | 42 ++++++ ...ng-activities-requiring-dependency-2c48.md | 42 ++++++ ...ss-cutting-activities-use-androidx-9fdc.md | 33 +++++ ...ss-cutting-activities-use-androidx-c392.md | 43 ++++++ ...-activity-implementations-override-4358.md | 42 ++++++ ...-additional-validation-constraints-be5d.md | 34 +++++ ...tting-android-activities-requiring-ea4b.md | 42 ++++++ ...utting-android-activity-components-668b.md | 47 ++++++ ...tting-android-framework-components-b803.md | 33 +++++ ...ross-cutting-application-class-use-7fe1.md | 38 +++++ ...ross-cutting-application-class-use-ed5f.md | 33 +++++ ...s-cutting-application-entry-points-442f.md | 46 ++++++ ...utting-application-specific-labels-53b2.md | 38 +++++ ...ng-asynchronous-operations-execute-34bb.md | 33 +++++ ...ss-cutting-automation-scripts-load-f44a.md | 43 ++++++ ...oss-cutting-avoid-manual-iteration-1ba7.md | 29 ++++ ...ss-cutting-boolean-flag-parameters-2f3c.md | 30 ++++ ...s-cutting-component-functions-that-68f3.md | 35 +++++ ...ross-cutting-components-use-inject-243c.md | 31 ++++ ...ss-cutting-composable-files-import-341a.md | 30 ++++ ...ing-composable-functions-integrate-9d19.md | 29 ++++ ...s-cutting-composable-functions-use-42ea.md | 30 ++++ ...s-cutting-composable-functions-use-f5e4.md | 36 +++++ ...s-cutting-composables-use-androidx-4aea.md | 34 +++++ ...utting-composables-use-columnscope-4c90.md | 36 +++++ ...g-configuration-define-application-f12f.md | 44 ++++++ ...ng-configuration-loading-functions-1ecc.md | 40 ++++++ ...-cutting-configuration-parsers-use-c30b.md | 38 +++++ ...ing-configuration-pattern-matching-2518.md | 46 ++++++ ...ng-custom-exception-bitwardenerror-198d.md | 36 +++++ ...tting-custom-kotlinx-serialization-7733.md | 36 +++++ ...g-dependencies-injected-activities-aa04.md | 39 +++++ ...ting-dependencies-injected-android-77ba.md | 46 ++++++ ...-cutting-dependency-injection-used-34c6.md | 33 +++++ ...ross-cutting-dialog-loading-states-c091.md | 40 ++++++ ...cutting-error-handling-distinguish-d0fc.md | 30 ++++ .../cross-cutting-error-log-entries-b607.md | 29 ++++ .../cross-cutting-error-logging-occur-5985.md | 29 ++++ ...oss-cutting-error-messages-include-a9af.md | 30 ++++ .../cross-cutting-error-response-body-f91a.md | 29 ++++ .../cross-cutting-error-response-json-c4e2.md | 29 ++++ ...s-cutting-extension-functions-that-9c9d.md | 35 +++++ .../cross-cutting-external-calls-add-5042.md | 35 +++++ .../cross-cutting-fatal-errors-logged-0e95.md | 34 +++++ .../cross-cutting-fatal-server-errors-5945.md | 35 +++++ .../cross-cutting-fatal-server-level-bc5d.md | 30 ++++ ...oss-cutting-file-system-operations-39de.md | 41 ++++++ ...ing-functions-interacting-external-ad14.md | 34 +++++ ...cutting-github-integration-scripts-f2fa.md | 34 +++++ ...g-github-interactions-encapsulated-dcfc.md | 35 +++++ ...tting-handler-functions-coordinate-0482.md | 29 ++++ ...ross-cutting-handler-functions-not-b9c3.md | 29 ++++ ...ross-cutting-handler-functions-use-5910.md | 36 +++++ ...-cutting-handler-screen-components-27e5.md | 35 +++++ .../cross-cutting-http-error-response-b6ac.md | 36 +++++ ...ing-implementations-extend-console-470c.md | 30 ++++ ...tting-implementations-extend-error-dbb8.md | 34 +++++ ...oss-cutting-input-validation-occur-478e.md | 31 ++++ ...cross-cutting-input-validation-zod-39c6.md | 36 +++++ ...ng-integration-components-separate-dbfa.md | 29 ++++ ...ss-cutting-integration-servers-use-a61c.md | 29 ++++ ...s-cutting-integration-test-scripts-537e.md | 34 +++++ ...ss-cutting-intent-processing-logic-1ad0.md | 35 +++++ ...tting-internal-functions-implement-3f09.md | 33 +++++ ...ross-cutting-internal-scripts-that-a6ed.md | 37 +++++ ...ross-cutting-internal-that-process-c6b2.md | 40 ++++++ ...s-cutting-json-configuration-files-8d59.md | 41 ++++++ .../cross-cutting-json-data-loading-4759.md | 33 +++++ ...s-cutting-json-object-construction-6557.md | 30 ++++ ...s-cutting-kotlin-network-libraries-a59d.md | 33 +++++ ...oss-cutting-label-accumulation-use-6360.md | 29 ++++ ...oss-cutting-label-assignment-logic-e610.md | 39 +++++ ...tting-label-manipulation-functions-1022.md | 35 +++++ ...ss-cutting-label-operations-handle-1a7c.md | 30 ++++ ...cross-cutting-label-operations-use-2e0e.md | 34 +++++ ...ss-cutting-libraries-provide-hooks-8771.md | 30 ++++ ...ross-cutting-library-error-logging-722f.md | 31 ++++ .../cross-cutting-library-modules-use-2f7e.md | 30 ++++ ...cutting-mcp-server-implementations-42f6.md | 43 ++++++ ...cutting-mcp-server-implementations-aae0.md | 34 +++++ .../cross-cutting-mcp-servers-import-394d.md | 35 +++++ .../cross-cutting-memory-data-access-7a73.md | 41 ++++++ ...utting-navigation-lifecycle-events-3457.md | 35 +++++ .../cross-cutting-nested-field-access-e0d3.md | 34 +++++ ...ting-numeric-coordinate-parameters-2d66.md | 39 +++++ ...oss-cutting-numeric-inputs-include-ae1a.md | 30 ++++ ...utting-numeric-inputs-representing-2f96.md | 35 +++++ ...utting-optional-parameters-declare-567e.md | 30 ++++ ...utting-optional-parameters-declare-8bf8.md | 30 ++++ ...s-cutting-pattern-matching-against-b313.md | 29 ++++ ...cutting-predicate-functions-passed-fc06.md | 29 ++++ ...ss-cutting-public-action-contracts-270f.md | 36 +++++ ...-cutting-public-contract-functions-0f60.md | 35 +++++ ...-cutting-public-contracts-exported-2e18.md | 41 ++++++ ...ross-cutting-public-endpoints-that-0acc.md | 29 ++++ ...ross-cutting-public-endpoints-tool-48f1.md | 41 ++++++ ...ross-cutting-public-test-contracts-600b.md | 42 ++++++ ...cross-cutting-public-tool-handlers-deff.md | 37 +++++ ...-cutting-python-automation-scripts-7c5d.md | 37 +++++ .../cross-cutting-python-test-classes-6e3e.md | 33 +++++ .../cross-cutting-python-test-files-de0b.md | 39 +++++ .../cross-cutting-python-test-methods-8229.md | 39 +++++ .../cross-cutting-python-test-modules-e4ca.md | 45 ++++++ .../cross-cutting-python-tests-use-cfac.md | 36 +++++ ...ross-cutting-real-time-integration-d898.md | 36 +++++ ...cutting-schema-definitions-specify-ed0c.md | 31 ++++ ...oss-cutting-screen-composables-use-3522.md | 39 +++++ ...ng-screen-implementations-separate-575c.md | 36 +++++ ...cutting-screen-implementations-use-73df.md | 39 +++++ ...tting-screen-level-implementations-c0e0.md | 35 +++++ .../cross-cutting-scripts-combine-get-4258.md | 36 +++++ ...utting-scripts-implement-exception-39f9.md | 41 ++++++ ...utting-scripts-provide-appropriate-5bf4.md | 31 ++++ .../cross-cutting-scripts-that-accept-b4a6.md | 38 +++++ .../cross-cutting-scripts-that-invoke-3033.md | 38 +++++ .../cross-cutting-scripts-use-direct-56b5.md | 35 +++++ ...ross-cutting-scripts-use-predicate-6be1.md | 33 +++++ ...cross-cutting-scripts-use-standard-13e8.md | 35 +++++ ...oss-cutting-scripts-use-subprocess-0907.md | 29 ++++ ...ss-cutting-serialization-tests-use-40e0.md | 39 +++++ ...cutting-serialization-tests-verify-8748.md | 40 ++++++ ...cutting-server-implementations-use-4884.md | 46 ++++++ ...ting-server-initialization-declare-ebc9.md | 40 ++++++ ...s-cutting-server-instances-declare-2d8f.md | 29 ++++ ...-cutting-state-classes-implemented-3cf8.md | 41 ++++++ .../cross-cutting-state-updates-use-2449.md | 33 +++++ ...s-cutting-stdio-transport-imported-10ae.md | 37 +++++ ...-cutting-test-assertions-verifying-cd9f.md | 31 ++++ .../cross-cutting-test-classes-follow-9b1c.md | 38 +++++ ...oss-cutting-test-classes-implement-2b73.md | 42 ++++++ ...oss-cutting-test-classes-implement-772c.md | 31 ++++ ...oss-cutting-test-classes-implement-dead.md | 39 +++++ ...cross-cutting-test-classes-inherit-bf00.md | 41 ++++++ ...ross-cutting-test-classes-organize-d158.md | 29 ++++ ...ross-cutting-test-descriptions-use-18ee.md | 30 ++++ ...ss-cutting-test-fixtures-organized-85db.md | 42 ++++++ .../cross-cutting-test-fixtures-use-0e93.md | 42 ++++++ .../cross-cutting-test-method-names-f006.md | 33 +++++ ...cross-cutting-test-methods-include-02ab.md | 41 ++++++ .../cross-cutting-test-methods-use-27a4.md | 30 ++++ ...oss-cutting-test-methods-verifying-597c.md | 30 ++++ ...ing-test-specifications-typescript-ff88.md | 43 ++++++ ...ross-cutting-tests-suppress-stdout-270e.md | 41 ++++++ ...-cutting-tests-use-buildjsonobject-c361.md | 35 +++++ .../cross-cutting-tests-use-mock-0deb.md | 44 ++++++ .../cross-cutting-tests-use-mocking-4a66.md | 37 +++++ .../cross-cutting-tests-verify-both-6b75.md | 45 ++++++ ...ting-timing-parameters-waitseconds-72ef.md | 36 +++++ ...ss-cutting-tool-based-integrations-2f80.md | 29 ++++ .../cross-cutting-tool-error-logs-faca.md | 37 +++++ .../cross-cutting-tool-errors-logged-54a4.md | 33 +++++ ...ross-cutting-tool-execution-errors-9c42.md | 29 ++++ ...-cutting-tool-handlers-implemented-e293.md | 37 +++++ ...cross-cutting-tool-handlers-import-9bfd.md | 38 +++++ .../cross-cutting-tool-handlers-that-5b55.md | 35 +++++ ...utting-tool-implementations-export-cf91.md | 29 ++++ ...utting-tool-implementations-import-f8f4.md | 37 +++++ ...g-tool-implementations-modularized-ceec.md | 39 +++++ ...oss-cutting-tool-lookup-operations-3695.md | 33 +++++ .../cross-cutting-tool-lookup-use-e58a.md | 34 +++++ ...ross-cutting-tool-modules-separate-8b2d.md | 29 ++++ ...-cutting-type-definitions-imported-e555.md | 42 ++++++ ...e-definitions-modelcontextprotocol-3508.md | 29 ++++ ...s-cutting-typescript-libraries-use-0a85.md | 30 ++++ ...ross-cutting-typescript-test-files-3a62.md | 36 +++++ ...ross-cutting-typescript-test-files-dbef.md | 40 ++++++ ...ss-cutting-typescript-test-modules-d6b5.md | 40 ++++++ ...-cutting-typescript-tests-organize-9c5a.md | 37 +++++ ...cutting-use-alternative-collection-7913.md | 37 +++++ .../cross-cutting-use-array-find-3f88.md | 33 +++++ ...ross-cutting-use-custom-validation-0705.md | 31 ++++ .../rules/cross-cutting-use-set-add-a890.md | 36 +++++ ...cutting-validation-failures-result-13ac.md | 30 ++++ ...-cutting-validation-schemas-define-a0dd.md | 42 ++++++ ...cutting-validation-schemas-include-3c4f.md | 38 +++++ ...oss-cutting-validation-schemas-use-9f64.md | 37 +++++ ...g-validation-utilities-centralized-f02d.md | 42 ++++++ ...ting-validation-utilities-imported-0c4d.md | 41 ++++++ ...ing-validation-utilities-separated-c0da.md | 38 +++++ ...utting-viewmodel-classes-annotated-37e9.md | 40 ++++++ ...viewmodels-annotated-hiltviewmodel-b639.md | 38 +++++ ...ng-viewmodels-extend-baseviewmodel-3cae.md | 44 ++++++ ...ng-viewmodels-extend-baseviewmodel-cc3e.md | 41 ++++++ ...utting-viewmodels-handling-android-4582.md | 34 +++++ ...tting-viewmodels-handling-external-c129.md | 35 +++++ ...cutting-viewmodels-inject-multiple-c778.md | 35 +++++ ...viewmodels-inject-savedstatehandle-66c4.md | 42 ++++++ ...tting-viewmodels-public-boundaries-67b3.md | 34 +++++ ...ng-viewmodels-requiring-dependency-bc78.md | 36 +++++ ...cutting-viewmodels-use-constructor-14cc.md | 40 ++++++ ...cutting-viewmodels-use-constructor-b4ab.md | 38 +++++ ...ng-viewmodels-use-mutablestateflow-8c03.md | 39 +++++ ...s-cutting-when-type-discriminators-5dab.md | 30 ++++ ...oss-cutting-xml-parsing-operations-dd22.md | 40 ++++++ AGENTS.md | 55 +++++++ CLAUDE.md | 55 +++++++ ...teardown-lifecycle-test-methods-include.md | 116 +++++++++++++++ ...operations-handler-functions-coordinate.md | 120 ++++++++++++++++ ...lic-api-endpoints-use-custom-validation.md | 122 ++++++++++++++++ ...in-pr-automation-scripts-use-subprocess.md | 117 +++++++++++++++ ...g-in-libraries-typescript-libraries-use.md | 117 +++++++++++++++ ...lic-api-endpoints-public-endpoints-that.md | 122 ++++++++++++++++ ...api-tools-validation-utilities-imported.md | 112 +++++++++++++++ ...with-type-discriminators-tests-use-mock.md | 116 +++++++++++++++ ...up-teardown-lifecycle-test-fixtures-use.md | 116 +++++++++++++++ ...-device-integration-fatal-errors-logged.md | 123 ++++++++++++++++ ...on-automation-public-contract-functions.md | 99 +++++++++++++ ...automation-label-manipulation-functions.md | 99 +++++++++++++ ...ce-integration-stdio-transport-imported.md | 123 ++++++++++++++++ ...pi-endpoints-validation-failures-result.md | 122 ++++++++++++++++ ...gration-automation-scripts-use-standard.md | 99 +++++++++++++ ...n-components-viewmodels-use-constructor.md | 123 ++++++++++++++++ ...esting-frameworks-test-descriptions-use.md | 113 +++++++++++++++ ...sponses-custom-exception-bitwardenerror.md | 117 +++++++++++++++ ...ient-boundaries-label-operations-handle.md | 115 +++++++++++++++ ...-api-boundaries-intent-processing-logic.md | 116 +++++++++++++++ ...ory-data-queries-avoid-manual-iteration.md | 100 +++++++++++++ ...omation-configuration-loading-functions.md | 99 +++++++++++++ ...ecycle-management-components-use-inject.md | 126 ++++++++++++++++ ...-for-state-management-state-updates-use.md | 134 ++++++++++++++++++ ...undaries-configuration-pattern-matching.md | 115 +++++++++++++++ ...eardown-lifecycle-tests-suppress-stdout.md | 116 +++++++++++++++ ...-api-boundaries-public-action-contracts.md | 116 +++++++++++++++ ...-okhttp-mock-responses-test-methods-use.md | 117 +++++++++++++++ ...t-declaration-handler-screen-components.md | 123 ++++++++++++++++ ...ardown-lifecycle-test-classes-implement.md | 116 +++++++++++++++ ...-points-activities-requiring-dependency.md | 125 ++++++++++++++++ ...arameters-numeric-coordinate-parameters.md | 116 +++++++++++++++ ...ce-integration-server-instances-declare.md | 123 ++++++++++++++++ ...s-in-pr-automation-label-operations-use.md | 117 +++++++++++++++ ...lic-api-tools-public-contracts-exported.md | 112 +++++++++++++++ ...nput-parameters-boolean-flag-parameters.md | 116 +++++++++++++++ ...ogging-in-libraries-library-modules-use.md | 117 +++++++++++++++ ...ice-integration-tool-based-integrations.md | 123 ++++++++++++++++ ...-xml-parser-numeric-inputs-representing.md | 117 +++++++++++++++ ...nfiguration-parsers-scripts-that-invoke.md | 118 +++++++++++++++ ...ent-declaration-composable-files-import.md | 123 ++++++++++++++++ ...oid-screens-navigation-lifecycle-events.md | 118 +++++++++++++++ ...agement-asynchronous-operations-execute.md | 134 ++++++++++++++++++ ...on-components-dependency-injection-used.md | 123 ++++++++++++++++ ...n-type-definitions-modelcontextprotocol.md | 123 ++++++++++++++++ ...-android-screens-screen-composables-use.md | 118 +++++++++++++++ ...t-in-mcp-servers-tool-lookup-operations.md | 114 +++++++++++++++ ...-components-viewmodel-classes-annotated.md | 123 ++++++++++++++++ ...-based-error-logging-mcp-servers-import.md | 114 +++++++++++++++ ...or-tool-operations-input-validation-zod.md | 120 ++++++++++++++++ ...tomation-scripts-file-system-operations.md | 118 +++++++++++++++ ...-automation-scripts-implement-exception.md | 117 +++++++++++++++ ...on-and-typescript-typescript-test-files.md | 120 ++++++++++++++++ ...ic-api-tools-validation-schemas-include.md | 112 +++++++++++++++ ...agement-viewmodels-extend-baseviewmodel.md | 134 ++++++++++++++++++ ...te-management-state-classes-implemented.md | 134 ++++++++++++++++++ ...on-parsers-internal-functions-implement.md | 118 +++++++++++++++ ...r-in-memory-data-queries-use-array-find.md | 100 +++++++++++++ ...-discriminators-serialization-tests-use.md | 116 +++++++++++++++ ...integration-testing-scripts-combine-get.md | 114 +++++++++++++++ ...nt-declaration-composable-functions-use.md | 123 ++++++++++++++++ ...-integration-mcp-server-implementations.md | 123 ++++++++++++++++ ...oints-activity-implementations-override.md | 125 ++++++++++++++++ ...n-entry-points-application-entry-points.md | 125 ++++++++++++++++ ...-boundaries-viewmodels-handling-android.md | 116 +++++++++++++++ ...-servers-implementations-extend-console.md | 114 +++++++++++++++ ...nd-automation-scripts-json-data-loading.md | 118 +++++++++++++++ ...ic-api-endpoints-input-validation-occur.md | 122 ++++++++++++++++ ...rror-logging-server-implementations-use.md | 114 +++++++++++++++ ...d-fast-xml-parser-public-endpoints-tool.md | 117 +++++++++++++++ ...python-and-typescript-tests-use-mocking.md | 120 ++++++++++++++++ ...ndroid-screens-composables-use-androidx.md | 118 +++++++++++++++ ...oid-screens-composables-use-columnscope.md | 118 +++++++++++++++ ...al-client-boundaries-external-calls-add.md | 115 +++++++++++++++ ...ration-testing-integration-test-scripts.md | 114 +++++++++++++++ ...-boundaries-application-specific-labels.md | 115 +++++++++++++++ ...d-device-integration-tool-errors-logged.md | 123 ++++++++++++++++ ...i-endpoints-optional-parameters-declare.md | 122 ++++++++++++++++ ...-integration-testing-scripts-use-direct.md | 114 +++++++++++++++ ...screens-screen-implementations-separate.md | 118 +++++++++++++++ ...r-tool-operations-handler-functions-use.md | 120 ++++++++++++++++ ...based-error-logging-fatal-server-errors.md | 114 +++++++++++++++ ...ion-construction-test-methods-verifying.md | 101 +++++++++++++ ...text-in-mcp-servers-error-logging-occur.md | 114 +++++++++++++++ ...ool-input-parameters-tool-handlers-that.md | 116 +++++++++++++++ ...ion-testing-scripts-provide-appropriate.md | 114 +++++++++++++++ ...discriminators-when-type-discriminators.md | 116 +++++++++++++++ ...eardown-lifecycle-public-test-contracts.md | 116 +++++++++++++++ ...lient-boundaries-label-accumulation-use.md | 115 +++++++++++++++ ...n-construction-json-object-construction.md | 101 +++++++++++++ ...-components-android-activity-components.md | 123 ++++++++++++++++ ...ment-viewmodels-inject-savedstatehandle.md | 134 ++++++++++++++++++ ...boundaries-viewmodels-public-boundaries.md | 116 +++++++++++++++ ...nt-declaration-component-functions-that.md | 123 ++++++++++++++++ ...rd-testing-frameworks-tests-verify-both.md | 113 +++++++++++++++ ...utomation-scripts-scripts-use-predicate.md | 118 +++++++++++++++ ...thon-and-typescript-python-test-classes.md | 120 ++++++++++++++++ ...ging-in-libraries-library-error-logging.md | 117 +++++++++++++++ ...arameters-timing-parameters-waitseconds.md | 116 +++++++++++++++ ...roid-screens-screen-implementations-use.md | 118 +++++++++++++++ ...sting-frameworks-test-classes-implement.md | 113 +++++++++++++++ ...riminators-custom-kotlinx-serialization.md | 116 +++++++++++++++ ...anagement-dependencies-injected-android.md | 126 ++++++++++++++++ ...data-queries-use-alternative-collection.md | 100 +++++++++++++ ...d-automation-scripts-memory-data-access.md | 118 +++++++++++++++ ...ation-scripts-python-automation-scripts.md | 118 +++++++++++++++ ...-activities-extending-componentactivity.md | 126 ++++++++++++++++ ...ecycle-management-application-class-use.md | 126 ++++++++++++++++ ...-testing-frameworks-python-test-methods.md | 113 +++++++++++++++ ...ting-frameworks-test-fixtures-organized.md | 113 +++++++++++++++ ...construction-serialization-tests-verify.md | 101 +++++++++++++ ...ng-in-libraries-libraries-provide-hooks.md | 117 +++++++++++++++ ...r-tool-operations-tool-modules-separate.md | 120 ++++++++++++++++ ...-parameters-optional-parameters-declare.md | 116 +++++++++++++++ ...agement-viewmodels-use-mutablestateflow.md | 134 ++++++++++++++++++ ...ast-xml-parser-json-configuration-files.md | 117 +++++++++++++++ ...type-discriminators-test-classes-follow.md | 116 +++++++++++++++ ...r-public-api-tools-tool-handlers-import.md | 112 +++++++++++++++ ...xt-in-mcp-servers-tool-execution-errors.md | 114 +++++++++++++++ ...nd-typescript-typescript-tests-organize.md | 120 ++++++++++++++++ ...discriminators-extension-functions-that.md | 116 +++++++++++++++ ...-screens-composable-functions-integrate.md | 118 +++++++++++++++ ...public-api-tools-validation-schemas-use.md | 112 +++++++++++++++ ...on-entry-points-activities-use-androidx.md | 125 ++++++++++++++++ ...st-xml-parser-validation-schemas-define.md | 117 +++++++++++++++ ...g-in-libraries-kotlin-network-libraries.md | 117 +++++++++++++++ ...ice-integration-integration-servers-use.md | 123 ++++++++++++++++ ...iguration-parsers-internal-scripts-that.md | 118 +++++++++++++++ ...-for-in-memory-data-queries-use-set-add.md | 100 +++++++++++++ ...t-in-mcp-servers-error-messages-include.md | 114 +++++++++++++++ ...onents-dependencies-injected-activities.md | 123 ++++++++++++++++ ...rror-logging-mcp-server-implementations.md | 114 +++++++++++++++ ...tomation-functions-interacting-external.md | 99 +++++++++++++ ...ic-api-endpoints-numeric-inputs-include.md | 122 ++++++++++++++++ ...ent-boundaries-pattern-matching-against.md | 115 +++++++++++++++ ...nfiguration-parsers-scripts-that-accept.md | 118 +++++++++++++++ ...e-management-viewmodels-use-constructor.md | 126 ++++++++++++++++ ...-logging-in-libraries-error-log-entries.md | 117 +++++++++++++++ ...ment-viewmodels-annotated-hiltviewmodel.md | 134 ++++++++++++++++++ ...http-mock-responses-http-error-response.md | 117 +++++++++++++++ ...components-android-framework-components.md | 123 ++++++++++++++++ ...r-tool-operations-handler-functions-not.md | 120 ++++++++++++++++ ...ntext-in-mcp-servers-fatal-server-level.md | 114 +++++++++++++++ ...agement-viewmodels-requiring-dependency.md | 126 ++++++++++++++++ ...arser-additional-validation-constraints.md | 117 +++++++++++++++ ...teardown-lifecycle-test-classes-inherit.md | 116 +++++++++++++++ ...-state-management-dialog-loading-states.md | 134 ++++++++++++++++++ ...egration-validation-utilities-separated.md | 123 ++++++++++++++++ ...eclaration-screen-level-implementations.md | 123 ++++++++++++++++ ...boundaries-viewmodels-handling-external.md | 116 +++++++++++++++ ...ation-parsers-configuration-parsers-use.md | 118 +++++++++++++++ ...-construction-tests-use-buildjsonobject.md | 101 +++++++++++++ ...on-entry-points-activities-use-androidx.md | 125 ++++++++++++++++ ...http-mock-responses-error-response-json.md | 117 +++++++++++++++ ...iguration-parsers-internal-that-process.md | 118 +++++++++++++++ ...i-boundaries-viewmodels-inject-multiple.md | 116 +++++++++++++++ ...-points-viewmodels-extend-baseviewmodel.md | 125 ++++++++++++++++ ...-construction-test-assertions-verifying.md | 101 +++++++++++++ ...ration-tool-implementations-modularized.md | 123 ++++++++++++++++ ...-operations-tool-implementations-export.md | 120 ++++++++++++++++ ...-python-and-typescript-python-tests-use.md | 120 ++++++++++++++++ ...-integration-error-handling-distinguish.md | 123 ++++++++++++++++ ...tp-mock-responses-test-classes-organize.md | 117 +++++++++++++++ ...ting-frameworks-typescript-test-modules.md | 113 +++++++++++++++ ...evice-integration-real-time-integration.md | 123 ++++++++++++++++ ...or-logging-implementations-extend-error.md | 114 +++++++++++++++ ...esting-frameworks-typescript-test-files.md | 113 +++++++++++++++ ...gration-integration-components-separate.md | 123 ++++++++++++++++ ...mation-github-interactions-encapsulated.md | 117 +++++++++++++++ ...-fast-xml-parser-xml-parsing-operations.md | 117 +++++++++++++++ ...entry-points-activities-handling-system.md | 125 ++++++++++++++++ ...python-and-typescript-python-test-files.md | 120 ++++++++++++++++ ...ardown-lifecycle-test-classes-implement.md | 116 +++++++++++++++ ...r-public-api-tools-public-tool-handlers.md | 112 +++++++++++++++ ...integration-testing-nested-field-access.md | 114 +++++++++++++++ ...lic-api-tools-tool-handlers-implemented.md | 112 +++++++++++++++ ...-testing-frameworks-python-test-modules.md | 113 +++++++++++++++ ...e-integration-type-definitions-imported.md | 123 ++++++++++++++++ ...roid-device-integration-tool-lookup-use.md | 123 ++++++++++++++++ ...in-pr-automation-label-assignment-logic.md | 117 +++++++++++++++ ...management-android-activities-requiring.md | 126 ++++++++++++++++ ...tegration-server-initialization-declare.md | 123 ++++++++++++++++ ...pi-endpoints-schema-definitions-specify.md | 122 ++++++++++++++++ ...cation-components-application-class-use.md | 123 ++++++++++++++++ ...python-and-typescript-test-method-names.md | 120 ++++++++++++++++ ...parser-validation-utilities-centralized.md | 117 +++++++++++++++ ...mation-configuration-define-application.md | 117 +++++++++++++++ ...n-automation-github-integration-scripts.md | 99 +++++++++++++ ...n-pr-automation-automation-scripts-load.md | 117 +++++++++++++++ ...nt-declaration-composable-functions-use.md | 123 ++++++++++++++++ ...-parameters-tool-implementations-import.md | 116 +++++++++++++++ ...http-mock-responses-error-response-body.md | 117 +++++++++++++++ ...ole-based-error-logging-tool-error-logs.md | 114 +++++++++++++++ ...data-queries-predicate-functions-passed.md | 100 +++++++++++++ ...-scripts-test-specifications-typescript.md | 118 +++++++++++++++ 392 files changed, 29995 insertions(+) create mode 100644 .actual/rules/cross-cutting-activities-extending-componentactivity-7f82.md create mode 100644 .actual/rules/cross-cutting-activities-handling-system-ddfe.md create mode 100644 .actual/rules/cross-cutting-activities-requiring-dependency-2c48.md create mode 100644 .actual/rules/cross-cutting-activities-use-androidx-9fdc.md create mode 100644 .actual/rules/cross-cutting-activities-use-androidx-c392.md create mode 100644 .actual/rules/cross-cutting-activity-implementations-override-4358.md create mode 100644 .actual/rules/cross-cutting-additional-validation-constraints-be5d.md create mode 100644 .actual/rules/cross-cutting-android-activities-requiring-ea4b.md create mode 100644 .actual/rules/cross-cutting-android-activity-components-668b.md create mode 100644 .actual/rules/cross-cutting-android-framework-components-b803.md create mode 100644 .actual/rules/cross-cutting-application-class-use-7fe1.md create mode 100644 .actual/rules/cross-cutting-application-class-use-ed5f.md create mode 100644 .actual/rules/cross-cutting-application-entry-points-442f.md create mode 100644 .actual/rules/cross-cutting-application-specific-labels-53b2.md create mode 100644 .actual/rules/cross-cutting-asynchronous-operations-execute-34bb.md create mode 100644 .actual/rules/cross-cutting-automation-scripts-load-f44a.md create mode 100644 .actual/rules/cross-cutting-avoid-manual-iteration-1ba7.md create mode 100644 .actual/rules/cross-cutting-boolean-flag-parameters-2f3c.md create mode 100644 .actual/rules/cross-cutting-component-functions-that-68f3.md create mode 100644 .actual/rules/cross-cutting-components-use-inject-243c.md create mode 100644 .actual/rules/cross-cutting-composable-files-import-341a.md create mode 100644 .actual/rules/cross-cutting-composable-functions-integrate-9d19.md create mode 100644 .actual/rules/cross-cutting-composable-functions-use-42ea.md create mode 100644 .actual/rules/cross-cutting-composable-functions-use-f5e4.md create mode 100644 .actual/rules/cross-cutting-composables-use-androidx-4aea.md create mode 100644 .actual/rules/cross-cutting-composables-use-columnscope-4c90.md create mode 100644 .actual/rules/cross-cutting-configuration-define-application-f12f.md create mode 100644 .actual/rules/cross-cutting-configuration-loading-functions-1ecc.md create mode 100644 .actual/rules/cross-cutting-configuration-parsers-use-c30b.md create mode 100644 .actual/rules/cross-cutting-configuration-pattern-matching-2518.md create mode 100644 .actual/rules/cross-cutting-custom-exception-bitwardenerror-198d.md create mode 100644 .actual/rules/cross-cutting-custom-kotlinx-serialization-7733.md create mode 100644 .actual/rules/cross-cutting-dependencies-injected-activities-aa04.md create mode 100644 .actual/rules/cross-cutting-dependencies-injected-android-77ba.md create mode 100644 .actual/rules/cross-cutting-dependency-injection-used-34c6.md create mode 100644 .actual/rules/cross-cutting-dialog-loading-states-c091.md create mode 100644 .actual/rules/cross-cutting-error-handling-distinguish-d0fc.md create mode 100644 .actual/rules/cross-cutting-error-log-entries-b607.md create mode 100644 .actual/rules/cross-cutting-error-logging-occur-5985.md create mode 100644 .actual/rules/cross-cutting-error-messages-include-a9af.md create mode 100644 .actual/rules/cross-cutting-error-response-body-f91a.md create mode 100644 .actual/rules/cross-cutting-error-response-json-c4e2.md create mode 100644 .actual/rules/cross-cutting-extension-functions-that-9c9d.md create mode 100644 .actual/rules/cross-cutting-external-calls-add-5042.md create mode 100644 .actual/rules/cross-cutting-fatal-errors-logged-0e95.md create mode 100644 .actual/rules/cross-cutting-fatal-server-errors-5945.md create mode 100644 .actual/rules/cross-cutting-fatal-server-level-bc5d.md create mode 100644 .actual/rules/cross-cutting-file-system-operations-39de.md create mode 100644 .actual/rules/cross-cutting-functions-interacting-external-ad14.md create mode 100644 .actual/rules/cross-cutting-github-integration-scripts-f2fa.md create mode 100644 .actual/rules/cross-cutting-github-interactions-encapsulated-dcfc.md create mode 100644 .actual/rules/cross-cutting-handler-functions-coordinate-0482.md create mode 100644 .actual/rules/cross-cutting-handler-functions-not-b9c3.md create mode 100644 .actual/rules/cross-cutting-handler-functions-use-5910.md create mode 100644 .actual/rules/cross-cutting-handler-screen-components-27e5.md create mode 100644 .actual/rules/cross-cutting-http-error-response-b6ac.md create mode 100644 .actual/rules/cross-cutting-implementations-extend-console-470c.md create mode 100644 .actual/rules/cross-cutting-implementations-extend-error-dbb8.md create mode 100644 .actual/rules/cross-cutting-input-validation-occur-478e.md create mode 100644 .actual/rules/cross-cutting-input-validation-zod-39c6.md create mode 100644 .actual/rules/cross-cutting-integration-components-separate-dbfa.md create mode 100644 .actual/rules/cross-cutting-integration-servers-use-a61c.md create mode 100644 .actual/rules/cross-cutting-integration-test-scripts-537e.md create mode 100644 .actual/rules/cross-cutting-intent-processing-logic-1ad0.md create mode 100644 .actual/rules/cross-cutting-internal-functions-implement-3f09.md create mode 100644 .actual/rules/cross-cutting-internal-scripts-that-a6ed.md create mode 100644 .actual/rules/cross-cutting-internal-that-process-c6b2.md create mode 100644 .actual/rules/cross-cutting-json-configuration-files-8d59.md create mode 100644 .actual/rules/cross-cutting-json-data-loading-4759.md create mode 100644 .actual/rules/cross-cutting-json-object-construction-6557.md create mode 100644 .actual/rules/cross-cutting-kotlin-network-libraries-a59d.md create mode 100644 .actual/rules/cross-cutting-label-accumulation-use-6360.md create mode 100644 .actual/rules/cross-cutting-label-assignment-logic-e610.md create mode 100644 .actual/rules/cross-cutting-label-manipulation-functions-1022.md create mode 100644 .actual/rules/cross-cutting-label-operations-handle-1a7c.md create mode 100644 .actual/rules/cross-cutting-label-operations-use-2e0e.md create mode 100644 .actual/rules/cross-cutting-libraries-provide-hooks-8771.md create mode 100644 .actual/rules/cross-cutting-library-error-logging-722f.md create mode 100644 .actual/rules/cross-cutting-library-modules-use-2f7e.md create mode 100644 .actual/rules/cross-cutting-mcp-server-implementations-42f6.md create mode 100644 .actual/rules/cross-cutting-mcp-server-implementations-aae0.md create mode 100644 .actual/rules/cross-cutting-mcp-servers-import-394d.md create mode 100644 .actual/rules/cross-cutting-memory-data-access-7a73.md create mode 100644 .actual/rules/cross-cutting-navigation-lifecycle-events-3457.md create mode 100644 .actual/rules/cross-cutting-nested-field-access-e0d3.md create mode 100644 .actual/rules/cross-cutting-numeric-coordinate-parameters-2d66.md create mode 100644 .actual/rules/cross-cutting-numeric-inputs-include-ae1a.md create mode 100644 .actual/rules/cross-cutting-numeric-inputs-representing-2f96.md create mode 100644 .actual/rules/cross-cutting-optional-parameters-declare-567e.md create mode 100644 .actual/rules/cross-cutting-optional-parameters-declare-8bf8.md create mode 100644 .actual/rules/cross-cutting-pattern-matching-against-b313.md create mode 100644 .actual/rules/cross-cutting-predicate-functions-passed-fc06.md create mode 100644 .actual/rules/cross-cutting-public-action-contracts-270f.md create mode 100644 .actual/rules/cross-cutting-public-contract-functions-0f60.md create mode 100644 .actual/rules/cross-cutting-public-contracts-exported-2e18.md create mode 100644 .actual/rules/cross-cutting-public-endpoints-that-0acc.md create mode 100644 .actual/rules/cross-cutting-public-endpoints-tool-48f1.md create mode 100644 .actual/rules/cross-cutting-public-test-contracts-600b.md create mode 100644 .actual/rules/cross-cutting-public-tool-handlers-deff.md create mode 100644 .actual/rules/cross-cutting-python-automation-scripts-7c5d.md create mode 100644 .actual/rules/cross-cutting-python-test-classes-6e3e.md create mode 100644 .actual/rules/cross-cutting-python-test-files-de0b.md create mode 100644 .actual/rules/cross-cutting-python-test-methods-8229.md create mode 100644 .actual/rules/cross-cutting-python-test-modules-e4ca.md create mode 100644 .actual/rules/cross-cutting-python-tests-use-cfac.md create mode 100644 .actual/rules/cross-cutting-real-time-integration-d898.md create mode 100644 .actual/rules/cross-cutting-schema-definitions-specify-ed0c.md create mode 100644 .actual/rules/cross-cutting-screen-composables-use-3522.md create mode 100644 .actual/rules/cross-cutting-screen-implementations-separate-575c.md create mode 100644 .actual/rules/cross-cutting-screen-implementations-use-73df.md create mode 100644 .actual/rules/cross-cutting-screen-level-implementations-c0e0.md create mode 100644 .actual/rules/cross-cutting-scripts-combine-get-4258.md create mode 100644 .actual/rules/cross-cutting-scripts-implement-exception-39f9.md create mode 100644 .actual/rules/cross-cutting-scripts-provide-appropriate-5bf4.md create mode 100644 .actual/rules/cross-cutting-scripts-that-accept-b4a6.md create mode 100644 .actual/rules/cross-cutting-scripts-that-invoke-3033.md create mode 100644 .actual/rules/cross-cutting-scripts-use-direct-56b5.md create mode 100644 .actual/rules/cross-cutting-scripts-use-predicate-6be1.md create mode 100644 .actual/rules/cross-cutting-scripts-use-standard-13e8.md create mode 100644 .actual/rules/cross-cutting-scripts-use-subprocess-0907.md create mode 100644 .actual/rules/cross-cutting-serialization-tests-use-40e0.md create mode 100644 .actual/rules/cross-cutting-serialization-tests-verify-8748.md create mode 100644 .actual/rules/cross-cutting-server-implementations-use-4884.md create mode 100644 .actual/rules/cross-cutting-server-initialization-declare-ebc9.md create mode 100644 .actual/rules/cross-cutting-server-instances-declare-2d8f.md create mode 100644 .actual/rules/cross-cutting-state-classes-implemented-3cf8.md create mode 100644 .actual/rules/cross-cutting-state-updates-use-2449.md create mode 100644 .actual/rules/cross-cutting-stdio-transport-imported-10ae.md create mode 100644 .actual/rules/cross-cutting-test-assertions-verifying-cd9f.md create mode 100644 .actual/rules/cross-cutting-test-classes-follow-9b1c.md create mode 100644 .actual/rules/cross-cutting-test-classes-implement-2b73.md create mode 100644 .actual/rules/cross-cutting-test-classes-implement-772c.md create mode 100644 .actual/rules/cross-cutting-test-classes-implement-dead.md create mode 100644 .actual/rules/cross-cutting-test-classes-inherit-bf00.md create mode 100644 .actual/rules/cross-cutting-test-classes-organize-d158.md create mode 100644 .actual/rules/cross-cutting-test-descriptions-use-18ee.md create mode 100644 .actual/rules/cross-cutting-test-fixtures-organized-85db.md create mode 100644 .actual/rules/cross-cutting-test-fixtures-use-0e93.md create mode 100644 .actual/rules/cross-cutting-test-method-names-f006.md create mode 100644 .actual/rules/cross-cutting-test-methods-include-02ab.md create mode 100644 .actual/rules/cross-cutting-test-methods-use-27a4.md create mode 100644 .actual/rules/cross-cutting-test-methods-verifying-597c.md create mode 100644 .actual/rules/cross-cutting-test-specifications-typescript-ff88.md create mode 100644 .actual/rules/cross-cutting-tests-suppress-stdout-270e.md create mode 100644 .actual/rules/cross-cutting-tests-use-buildjsonobject-c361.md create mode 100644 .actual/rules/cross-cutting-tests-use-mock-0deb.md create mode 100644 .actual/rules/cross-cutting-tests-use-mocking-4a66.md create mode 100644 .actual/rules/cross-cutting-tests-verify-both-6b75.md create mode 100644 .actual/rules/cross-cutting-timing-parameters-waitseconds-72ef.md create mode 100644 .actual/rules/cross-cutting-tool-based-integrations-2f80.md create mode 100644 .actual/rules/cross-cutting-tool-error-logs-faca.md create mode 100644 .actual/rules/cross-cutting-tool-errors-logged-54a4.md create mode 100644 .actual/rules/cross-cutting-tool-execution-errors-9c42.md create mode 100644 .actual/rules/cross-cutting-tool-handlers-implemented-e293.md create mode 100644 .actual/rules/cross-cutting-tool-handlers-import-9bfd.md create mode 100644 .actual/rules/cross-cutting-tool-handlers-that-5b55.md create mode 100644 .actual/rules/cross-cutting-tool-implementations-export-cf91.md create mode 100644 .actual/rules/cross-cutting-tool-implementations-import-f8f4.md create mode 100644 .actual/rules/cross-cutting-tool-implementations-modularized-ceec.md create mode 100644 .actual/rules/cross-cutting-tool-lookup-operations-3695.md create mode 100644 .actual/rules/cross-cutting-tool-lookup-use-e58a.md create mode 100644 .actual/rules/cross-cutting-tool-modules-separate-8b2d.md create mode 100644 .actual/rules/cross-cutting-type-definitions-imported-e555.md create mode 100644 .actual/rules/cross-cutting-type-definitions-modelcontextprotocol-3508.md create mode 100644 .actual/rules/cross-cutting-typescript-libraries-use-0a85.md create mode 100644 .actual/rules/cross-cutting-typescript-test-files-3a62.md create mode 100644 .actual/rules/cross-cutting-typescript-test-files-dbef.md create mode 100644 .actual/rules/cross-cutting-typescript-test-modules-d6b5.md create mode 100644 .actual/rules/cross-cutting-typescript-tests-organize-9c5a.md create mode 100644 .actual/rules/cross-cutting-use-alternative-collection-7913.md create mode 100644 .actual/rules/cross-cutting-use-array-find-3f88.md create mode 100644 .actual/rules/cross-cutting-use-custom-validation-0705.md create mode 100644 .actual/rules/cross-cutting-use-set-add-a890.md create mode 100644 .actual/rules/cross-cutting-validation-failures-result-13ac.md create mode 100644 .actual/rules/cross-cutting-validation-schemas-define-a0dd.md create mode 100644 .actual/rules/cross-cutting-validation-schemas-include-3c4f.md create mode 100644 .actual/rules/cross-cutting-validation-schemas-use-9f64.md create mode 100644 .actual/rules/cross-cutting-validation-utilities-centralized-f02d.md create mode 100644 .actual/rules/cross-cutting-validation-utilities-imported-0c4d.md create mode 100644 .actual/rules/cross-cutting-validation-utilities-separated-c0da.md create mode 100644 .actual/rules/cross-cutting-viewmodel-classes-annotated-37e9.md create mode 100644 .actual/rules/cross-cutting-viewmodels-annotated-hiltviewmodel-b639.md create mode 100644 .actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-3cae.md create mode 100644 .actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-cc3e.md create mode 100644 .actual/rules/cross-cutting-viewmodels-handling-android-4582.md create mode 100644 .actual/rules/cross-cutting-viewmodels-handling-external-c129.md create mode 100644 .actual/rules/cross-cutting-viewmodels-inject-multiple-c778.md create mode 100644 .actual/rules/cross-cutting-viewmodels-inject-savedstatehandle-66c4.md create mode 100644 .actual/rules/cross-cutting-viewmodels-public-boundaries-67b3.md create mode 100644 .actual/rules/cross-cutting-viewmodels-requiring-dependency-bc78.md create mode 100644 .actual/rules/cross-cutting-viewmodels-use-constructor-14cc.md create mode 100644 .actual/rules/cross-cutting-viewmodels-use-constructor-b4ab.md create mode 100644 .actual/rules/cross-cutting-viewmodels-use-mutablestateflow-8c03.md create mode 100644 .actual/rules/cross-cutting-when-type-discriminators-5dab.md create mode 100644 .actual/rules/cross-cutting-xml-parsing-operations-dd22.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 docs/adr/02ab6269-efc6-43d8-8dab-11f6fad6e18c-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-methods-include.md create mode 100644 docs/adr/0482e3b2-d96e-4410-a1b3-bfaff3c52773-adopt-async-handler-pattern-for-tool-operations-handler-functions-coordinate.md create mode 100644 docs/adr/0705eaa1-53bb-4b7d-85c5-442ae28e26ac-enforce-schema-based-input-validation-for-public-api-endpoints-use-custom-validation.md create mode 100644 docs/adr/09073977-2366-4777-9cad-69ed4f5d103e-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-use-subprocess.md create mode 100644 docs/adr/0a858504-83de-443b-b3d8-56bb1f18bb5a-standardize-console-error-and-response-error-for-error-logging-in-libraries-typescript-libraries-use.md create mode 100644 docs/adr/0acc83c8-3c34-457a-9f19-eb7e32cc5e62-enforce-schema-based-input-validation-for-public-api-endpoints-public-endpoints-that.md create mode 100644 docs/adr/0c4ddb3c-4f75-4172-a5dd-e6815bf1c6f1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-utilities-imported.md create mode 100644 docs/adr/0deb24db-6744-474e-86e4-0084c8180782-standardize-kotlinx-serialization-json-testing-with-type-discriminators-tests-use-mock.md create mode 100644 docs/adr/0e93d40a-3759-43d3-ae74-525a465aa5a7-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-fixtures-use.md create mode 100644 docs/adr/0e95ad4a-c8ed-42a9-af64-2737d2ce5b48-adopt-model-context-protocol-sdk-for-android-device-integration-fatal-errors-logged.md create mode 100644 docs/adr/0f6063db-430f-4ec7-9201-c516c50a7078-standardize-public-contract-functions-for-github-integration-automation-public-contract-functions.md create mode 100644 docs/adr/1022ba63-742d-4d07-a9ca-ddf44b8b6f4a-standardize-public-contract-functions-for-github-integration-automation-label-manipulation-functions.md create mode 100644 docs/adr/10aeb070-b829-4092-aa40-68b28214a184-adopt-model-context-protocol-sdk-for-android-device-integration-stdio-transport-imported.md create mode 100644 docs/adr/13ace594-1891-4c1a-9207-864e5b351033-enforce-schema-based-input-validation-for-public-api-endpoints-validation-failures-result.md create mode 100644 docs/adr/13e82e07-7ed6-4df2-bd40-17cf7c29ed52-standardize-public-contract-functions-for-github-integration-automation-scripts-use-standard.md create mode 100644 docs/adr/14cc0f9f-3d16-42a8-a5ef-ba36349bf042-adopt-hilt-dependency-injection-for-android-application-components-viewmodels-use-constructor.md create mode 100644 docs/adr/18ee23ee-c8e0-463d-8d5a-4898ab14a630-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-descriptions-use.md create mode 100644 docs/adr/198d8e26-bd59-4514-bbb8-36b222726207-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-custom-exception-bitwardenerror.md create mode 100644 docs/adr/1a7cd7af-4fe9-4aee-afb0-4b1b9faa0cd4-standardize-set-based-label-management-for-external-client-boundaries-label-operations-handle.md create mode 100644 docs/adr/1ad0412a-5069-4826-818c-2d9c8afdc0df-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-intent-processing-logic.md create mode 100644 docs/adr/1ba7e0e8-f59d-4593-87e9-5ff0142cd818-standardize-collection-find-pattern-for-in-memory-data-queries-avoid-manual-iteration.md create mode 100644 docs/adr/1ecc1baf-393e-4a64-b544-82bf87d0fda2-standardize-public-contract-functions-for-github-integration-automation-configuration-loading-functions.md create mode 100644 docs/adr/243cb603-fb8b-4db7-9f37-18ff5b0c99fe-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-components-use-inject.md create mode 100644 docs/adr/2449364d-4257-4659-b3a9-4e88ad892e92-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-updates-use.md create mode 100644 docs/adr/25181f2a-4b4a-421b-aef2-cbc5c9b1949e-standardize-set-based-label-management-for-external-client-boundaries-configuration-pattern-matching.md create mode 100644 docs/adr/270e7300-2101-4791-bc58-0b9520e1145f-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-tests-suppress-stdout.md create mode 100644 docs/adr/270f5ea8-6f63-45b7-b26b-02e89a5929ca-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-public-action-contracts.md create mode 100644 docs/adr/27a4b14f-c454-4d0a-9fc6-5fee8f57ce91-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-methods-use.md create mode 100644 docs/adr/27e5a784-711c-42af-b6dd-7ab5561d68f1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-handler-screen-components.md create mode 100644 docs/adr/2b73f914-73c9-44f2-be05-509c1b7eb734-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md create mode 100644 docs/adr/2c48296f-6f1b-484f-a794-3d4af770e641-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-requiring-dependency.md create mode 100644 docs/adr/2d663395-aff0-4638-b8ed-0ade254d9757-adopt-zod-schema-validation-for-tool-input-parameters-numeric-coordinate-parameters.md create mode 100644 docs/adr/2d8fc4df-c881-4439-990d-de74ed8e0868-adopt-model-context-protocol-sdk-for-real-time-device-integration-server-instances-declare.md create mode 100644 docs/adr/2e0e51b9-ce85-493f-b4ee-423f63400418-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-operations-use.md create mode 100644 docs/adr/2e18e8d5-e460-4b7e-88a0-68d4f5d582b9-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-contracts-exported.md create mode 100644 docs/adr/2f3cbae9-8b64-4724-9f11-bd00c23c4653-adopt-zod-schema-validation-for-tool-input-parameters-boolean-flag-parameters.md create mode 100644 docs/adr/2f7ee62b-4dfb-485a-8c08-8718131a2325-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-modules-use.md create mode 100644 docs/adr/2f80d513-9981-40a9-b1ad-18f2cd79a59b-adopt-model-context-protocol-sdk-for-real-time-device-integration-tool-based-integrations.md create mode 100644 docs/adr/2f964d88-ec51-4f7f-82a0-79bd1246932b-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-numeric-inputs-representing.md create mode 100644 docs/adr/30332d55-ad46-4c91-b4a2-e7c1a79f37a0-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-invoke.md create mode 100644 docs/adr/341a988b-b32d-469a-a0ff-70671c52b46d-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-files-import.md create mode 100644 docs/adr/34575625-c418-4842-8fcc-12beb0210e02-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-navigation-lifecycle-events.md create mode 100644 docs/adr/34bbb099-aca5-4383-ac43-e7fa38bf8036-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-asynchronous-operations-execute.md create mode 100644 docs/adr/34c6892b-f9fa-4878-af0e-1f5462016952-adopt-hilt-dependency-injection-for-android-application-components-dependency-injection-used.md create mode 100644 docs/adr/3508da20-cca1-4896-bb22-11b5c9bc8431-adopt-model-context-protocol-sdk-for-real-time-device-integration-type-definitions-modelcontextprotocol.md create mode 100644 docs/adr/3522412b-75d3-403a-b692-053f3c8cfd0e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-composables-use.md create mode 100644 docs/adr/369552b7-50d1-4a9f-967a-17aa9e99288f-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-lookup-operations.md create mode 100644 docs/adr/37e9c4b9-11fc-4ddb-b1f8-9b38695ac6d0-adopt-hilt-dependency-injection-for-android-application-components-viewmodel-classes-annotated.md create mode 100644 docs/adr/394dd45f-d4b2-4184-83e2-5fd2fdc2959f-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-servers-import.md create mode 100644 docs/adr/39c6995b-ecab-4fe7-bea8-8c6d0f14d122-adopt-async-handler-pattern-for-tool-operations-input-validation-zod.md create mode 100644 docs/adr/39de29ab-fa4d-44f9-be50-6358eb14ca5f-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-file-system-operations.md create mode 100644 docs/adr/39f948de-aff4-47e6-95e7-0b3b2fb9fa9b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-implement-exception.md create mode 100644 docs/adr/3a62eecd-2793-47fe-8552-26629b08d87e-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-test-files.md create mode 100644 docs/adr/3c4f6334-326e-4af0-9e52-4693d07d104f-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-include.md create mode 100644 docs/adr/3caee969-a463-4602-a10a-a9d0ac8725fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-extend-baseviewmodel.md create mode 100644 docs/adr/3cf8eb73-bea4-4643-86bf-b694273ab96b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-classes-implemented.md create mode 100644 docs/adr/3f096b2b-bdbd-4efe-8762-adb7c08e57f3-enforce-input-validation-for-internal-api-configuration-parsers-internal-functions-implement.md create mode 100644 docs/adr/3f881fc6-f60d-48ce-b59c-a30ae2333de4-standardize-collection-find-pattern-for-in-memory-data-queries-use-array-find.md create mode 100644 docs/adr/40e0fe78-854d-4145-942b-c15fcae948ee-standardize-kotlinx-serialization-json-testing-with-type-discriminators-serialization-tests-use.md create mode 100644 docs/adr/4258dbf5-ca5a-43b8-aec7-6ca64a00e937-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-combine-get.md create mode 100644 docs/adr/42ea08ba-ec5f-4deb-a4f5-082aba434692-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md create mode 100644 docs/adr/42f674c8-a883-4f57-862a-e52d9c7e217a-adopt-model-context-protocol-sdk-for-android-device-integration-mcp-server-implementations.md create mode 100644 docs/adr/43586977-155f-4fca-831c-ecd83c5f923f-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activity-implementations-override.md create mode 100644 docs/adr/442fb2a9-4d0e-4770-8b45-817b45829b74-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-application-entry-points.md create mode 100644 docs/adr/45829dc1-79d0-4b6b-b98f-10f9cf88e1bf-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-android.md create mode 100644 docs/adr/470c2bc4-87ff-4400-a07b-fb279d52be45-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-implementations-extend-console.md create mode 100644 docs/adr/475964a8-a030-497f-8ce6-0cd39a8f5f03-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-json-data-loading.md create mode 100644 docs/adr/478e5fed-094b-4ef2-afc1-88f9aa6956a4-enforce-schema-based-input-validation-for-public-api-endpoints-input-validation-occur.md create mode 100644 docs/adr/48843ec7-e1ab-4e68-95a6-f2d29f81c835-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-server-implementations-use.md create mode 100644 docs/adr/48f13c3a-a7cc-4d35-9b74-a5b204d2451d-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-public-endpoints-tool.md create mode 100644 docs/adr/4a66eb0d-cd6e-4ff9-9141-68acdc062e52-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-tests-use-mocking.md create mode 100644 docs/adr/4aea4cc3-aecc-4def-a941-be94472e80e2-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-androidx.md create mode 100644 docs/adr/4c90fdd9-d9d1-4228-9ca7-c4e47c517fe1-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-columnscope.md create mode 100644 docs/adr/50429da5-fe1f-4c10-8c86-b3226b013d16-standardize-set-based-label-management-for-external-client-boundaries-external-calls-add.md create mode 100644 docs/adr/537e96b2-a713-4732-bd41-e78399595757-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-integration-test-scripts.md create mode 100644 docs/adr/53b25493-fa5e-4734-bb63-dbe38cf09832-standardize-set-based-label-management-for-external-client-boundaries-application-specific-labels.md create mode 100644 docs/adr/54a455ad-a22f-44a9-89e7-ec0b36cddbae-adopt-model-context-protocol-sdk-for-android-device-integration-tool-errors-logged.md create mode 100644 docs/adr/567e6deb-4b37-4322-83a0-0d882acc8bb1-enforce-schema-based-input-validation-for-public-api-endpoints-optional-parameters-declare.md create mode 100644 docs/adr/56b52c53-ab5b-4371-9e76-41f731828a0d-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-use-direct.md create mode 100644 docs/adr/575c687d-732e-4964-99df-666d2a785e8c-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-separate.md create mode 100644 docs/adr/591073da-b16d-422c-a912-e14441d427d0-adopt-async-handler-pattern-for-tool-operations-handler-functions-use.md create mode 100644 docs/adr/59455fca-b2b2-4ac4-b814-b47e9dc84402-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-fatal-server-errors.md create mode 100644 docs/adr/597c203b-68e5-47e1-b387-760021689b99-use-json-builder-dsl-for-test-assertion-construction-test-methods-verifying.md create mode 100644 docs/adr/59851339-3655-43a8-8e80-a25247c1f58d-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-logging-occur.md create mode 100644 docs/adr/5b55513f-9bc8-4c6d-a31b-ccff626de6ca-adopt-zod-schema-validation-for-tool-input-parameters-tool-handlers-that.md create mode 100644 docs/adr/5bf424b3-89eb-4096-8559-2239b4337494-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-provide-appropriate.md create mode 100644 docs/adr/5dab80b0-9a3b-4743-8d55-84d6db3f8171-standardize-kotlinx-serialization-json-testing-with-type-discriminators-when-type-discriminators.md create mode 100644 docs/adr/600b7997-bad6-44c8-8d7c-7eaee2b25819-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-public-test-contracts.md create mode 100644 docs/adr/63609e18-cbc0-489d-8d3a-719e16b42c27-standardize-set-based-label-management-for-external-client-boundaries-label-accumulation-use.md create mode 100644 docs/adr/65578697-b9b2-469e-b60a-75d8f7d82639-use-json-builder-dsl-for-test-assertion-construction-json-object-construction.md create mode 100644 docs/adr/668b18be-602f-4256-9ff1-cdb73bd4329a-adopt-hilt-dependency-injection-for-android-application-components-android-activity-components.md create mode 100644 docs/adr/66c4ea0f-5e64-4cdc-bb11-8ae3cdb5c69b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-inject-savedstatehandle.md create mode 100644 docs/adr/67b3466d-4c62-4a90-8600-c539cf78d7c4-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-public-boundaries.md create mode 100644 docs/adr/68f32bb1-c4fa-4894-a34c-c2b358509119-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-component-functions-that.md create mode 100644 docs/adr/6b752b5a-f0df-4dce-ad73-38ba239f157b-adopt-unittest-and-vitest-as-standard-testing-frameworks-tests-verify-both.md create mode 100644 docs/adr/6be14423-e197-4c2d-b1a4-364a8e436a4c-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-scripts-use-predicate.md create mode 100644 docs/adr/6e3e1b7f-9835-4724-84f8-c348d80e4aef-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-classes.md create mode 100644 docs/adr/722f54e6-84df-4098-bb25-b1a404fd7445-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-error-logging.md create mode 100644 docs/adr/72ef156e-bd9d-4bad-87fc-e4ecb337b03e-adopt-zod-schema-validation-for-tool-input-parameters-timing-parameters-waitseconds.md create mode 100644 docs/adr/73df07ab-a3ee-4ae4-95f3-55ea8d01548e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-use.md create mode 100644 docs/adr/772c14d7-cf35-44f6-8d91-f64c403cc25a-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-classes-implement.md create mode 100644 docs/adr/77336862-f4d2-43f8-9f85-1649fcc3fc0c-standardize-kotlinx-serialization-json-testing-with-type-discriminators-custom-kotlinx-serialization.md create mode 100644 docs/adr/77bab4bd-ee05-4209-af7b-5c3ed8a41b28-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-dependencies-injected-android.md create mode 100644 docs/adr/791389c7-39fe-4bfe-91d3-16d774336937-standardize-collection-find-pattern-for-in-memory-data-queries-use-alternative-collection.md create mode 100644 docs/adr/7a73643a-e287-430c-8108-7c1ab4049554-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-memory-data-access.md create mode 100644 docs/adr/7c5da194-79be-45e1-8dd2-fb82ce577b95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-python-automation-scripts.md create mode 100644 docs/adr/7f825e0c-d33b-43a0-ac74-3b7da9eefd92-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-activities-extending-componentactivity.md create mode 100644 docs/adr/7fe11545-7b45-4360-a8bc-2d5c37949407-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-application-class-use.md create mode 100644 docs/adr/822904f8-d778-409d-ab3f-a2f2d3bfbac0-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-methods.md create mode 100644 docs/adr/85dbd58a-e138-490a-ad09-20a2013a0794-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-fixtures-organized.md create mode 100644 docs/adr/874842c0-a39c-4d3a-b1a9-4349607256d3-use-json-builder-dsl-for-test-assertion-construction-serialization-tests-verify.md create mode 100644 docs/adr/87712dbb-078d-457f-a0d9-2400b5d8b012-standardize-console-error-and-response-error-for-error-logging-in-libraries-libraries-provide-hooks.md create mode 100644 docs/adr/8b2d3bbd-e62e-41da-846f-2a7b570dfef8-adopt-async-handler-pattern-for-tool-operations-tool-modules-separate.md create mode 100644 docs/adr/8bf8bb07-c7a7-4dc6-ae85-95c75ba9efd9-adopt-zod-schema-validation-for-tool-input-parameters-optional-parameters-declare.md create mode 100644 docs/adr/8c033a44-0889-415a-8770-e35d0d4c03fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-use-mutablestateflow.md create mode 100644 docs/adr/8d59b907-3996-4bdc-b0e6-38744356cc8f-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-json-configuration-files.md create mode 100644 docs/adr/9b1cd432-f6b2-4d64-949d-1ed6f8997b22-standardize-kotlinx-serialization-json-testing-with-type-discriminators-test-classes-follow.md create mode 100644 docs/adr/9bfdca65-6800-424e-96c4-a54a6ae4d05d-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-import.md create mode 100644 docs/adr/9c42ab5a-68cb-49ad-862a-c6599f730ae4-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-execution-errors.md create mode 100644 docs/adr/9c5ac160-2570-425b-91d6-cc6e790ed980-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-tests-organize.md create mode 100644 docs/adr/9c9dd63b-7128-418f-a8e3-558cd55fddac-standardize-kotlinx-serialization-json-testing-with-type-discriminators-extension-functions-that.md create mode 100644 docs/adr/9d193d2c-ca56-4e12-9dc7-0666fbb5267a-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composable-functions-integrate.md create mode 100644 docs/adr/9f645b4e-5542-4c5d-b627-a1751a2814c2-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-use.md create mode 100644 docs/adr/9fdc35ed-c47b-4d09-8fd2-26a59f632114-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md create mode 100644 docs/adr/a0dd2b99-65aa-464c-a96f-8bf0ae9dcf2e-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-schemas-define.md create mode 100644 docs/adr/a59d9d80-8ebf-4f68-9ead-eccacbe96b50-standardize-console-error-and-response-error-for-error-logging-in-libraries-kotlin-network-libraries.md create mode 100644 docs/adr/a61ccece-339e-4912-9357-9ce009aa78df-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-servers-use.md create mode 100644 docs/adr/a6ed72bc-a5df-4c46-9d97-33bf7399d1ae-enforce-input-validation-for-internal-api-configuration-parsers-internal-scripts-that.md create mode 100644 docs/adr/a8900d19-7ca6-4686-8b55-c46711fdb7b8-standardize-collection-find-pattern-for-in-memory-data-queries-use-set-add.md create mode 100644 docs/adr/a9af7708-c42b-43f6-b33a-c7922023a6a7-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-messages-include.md create mode 100644 docs/adr/aa048d39-56ef-4832-9afe-beb1af3da70c-adopt-hilt-dependency-injection-for-android-application-components-dependencies-injected-activities.md create mode 100644 docs/adr/aae0f285-d3e2-4c79-90f6-2ba6356f3559-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-server-implementations.md create mode 100644 docs/adr/ad140c48-3220-4bb1-9030-52b93713e782-standardize-public-contract-functions-for-github-integration-automation-functions-interacting-external.md create mode 100644 docs/adr/ae1aaeb8-5a76-49e0-9577-9342abbb66e6-enforce-schema-based-input-validation-for-public-api-endpoints-numeric-inputs-include.md create mode 100644 docs/adr/b313895b-a93e-400c-8b22-620c2abad425-standardize-set-based-label-management-for-external-client-boundaries-pattern-matching-against.md create mode 100644 docs/adr/b4a63d5b-ac50-4f21-82dc-20bff4ab68fc-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-accept.md create mode 100644 docs/adr/b4abce3f-6018-4a4b-a4ea-593f39ecd135-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-use-constructor.md create mode 100644 docs/adr/b607cb14-16bb-49df-a9c8-04f43e0c585b-standardize-console-error-and-response-error-for-error-logging-in-libraries-error-log-entries.md create mode 100644 docs/adr/b6399a6b-ae13-419a-ab12-6bfe49660899-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-annotated-hiltviewmodel.md create mode 100644 docs/adr/b6ac444b-c292-4cbc-90bc-80331575d6a6-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-http-error-response.md create mode 100644 docs/adr/b80305fd-3b3e-4655-b99a-700320564144-adopt-hilt-dependency-injection-for-android-application-components-android-framework-components.md create mode 100644 docs/adr/b9c30d98-d40b-4301-9516-0097cc202473-adopt-async-handler-pattern-for-tool-operations-handler-functions-not.md create mode 100644 docs/adr/bc5d0ec4-e4fb-4c43-945a-977c37f92a37-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-fatal-server-level.md create mode 100644 docs/adr/bc783d9d-976e-45d9-89e6-30ff07dcef64-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-requiring-dependency.md create mode 100644 docs/adr/be5d07aa-1fe6-479b-af16-ce09f73ce4b6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-additional-validation-constraints.md create mode 100644 docs/adr/bf0002f3-6984-42b2-aca2-730034c01e8b-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-inherit.md create mode 100644 docs/adr/c091855f-fd5f-46da-b033-7a6ab3a1fa54-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-dialog-loading-states.md create mode 100644 docs/adr/c0da1b83-7641-4636-94f2-6b7299cbd587-adopt-model-context-protocol-sdk-for-android-device-integration-validation-utilities-separated.md create mode 100644 docs/adr/c0e01dbb-c7d8-4249-9ff1-6b54930f33e1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-screen-level-implementations.md create mode 100644 docs/adr/c1294673-f723-4fa2-9d29-ed728b1b02f2-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-external.md create mode 100644 docs/adr/c30bec5f-0d33-43b4-b42b-6cea3b39c20a-enforce-input-validation-for-internal-api-configuration-parsers-configuration-parsers-use.md create mode 100644 docs/adr/c36190bb-c866-44bd-a3af-c6a04e54d73b-use-json-builder-dsl-for-test-assertion-construction-tests-use-buildjsonobject.md create mode 100644 docs/adr/c392ab05-f46c-43be-ac19-3bc5ce82c5e9-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md create mode 100644 docs/adr/c4e21335-6ee6-4833-9d24-9a8225827ff8-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-json.md create mode 100644 docs/adr/c6b2221d-a2a7-43d4-ac14-5a82f1353d03-enforce-input-validation-for-internal-api-configuration-parsers-internal-that-process.md create mode 100644 docs/adr/c77883cd-f54d-461e-825b-f33537a65086-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-inject-multiple.md create mode 100644 docs/adr/cc3efe3f-8dc4-4c51-99fb-c263092e61da-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-viewmodels-extend-baseviewmodel.md create mode 100644 docs/adr/cd9fb085-7d4d-4567-9f79-0b0dfc05be78-use-json-builder-dsl-for-test-assertion-construction-test-assertions-verifying.md create mode 100644 docs/adr/ceec2cd4-0327-4e63-817b-921b9a4415da-adopt-model-context-protocol-sdk-for-android-device-integration-tool-implementations-modularized.md create mode 100644 docs/adr/cf91fbd7-c73a-4797-aee1-f3d03d7995d0-adopt-async-handler-pattern-for-tool-operations-tool-implementations-export.md create mode 100644 docs/adr/cfac6e70-958b-4189-8289-9daed54c616a-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-tests-use.md create mode 100644 docs/adr/d0fc711e-daaf-43ac-8555-b20545adec9a-adopt-model-context-protocol-sdk-for-real-time-device-integration-error-handling-distinguish.md create mode 100644 docs/adr/d158cb0f-6daf-4b88-89e4-957f2b1b8826-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-classes-organize.md create mode 100644 docs/adr/d6b5a93c-a86e-48b5-ab0f-e66269b640ad-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-modules.md create mode 100644 docs/adr/d89870be-79f5-4b57-9124-0ebfa63ccf07-adopt-model-context-protocol-sdk-for-real-time-device-integration-real-time-integration.md create mode 100644 docs/adr/dbb825c6-c6c7-4a92-8d5a-239b88eff0bb-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-implementations-extend-error.md create mode 100644 docs/adr/dbef69a5-6060-40bb-a8cd-ec32d52b7119-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-files.md create mode 100644 docs/adr/dbfa248c-cae8-4b7a-86a3-b5500a8e6cee-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-components-separate.md create mode 100644 docs/adr/dcfc1578-9eef-45ea-aaab-245004231943-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-github-interactions-encapsulated.md create mode 100644 docs/adr/dd22b744-04ad-4bef-826b-11857803deae-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-xml-parsing-operations.md create mode 100644 docs/adr/ddfe2b69-49cf-4137-a3cf-95ba2ba77b05-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-handling-system.md create mode 100644 docs/adr/de0b6d27-1fae-4b8c-9a96-2aa4ce519252-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-files.md create mode 100644 docs/adr/deada6b8-5256-42f2-9304-3c6fcf5b13a9-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md create mode 100644 docs/adr/deff453e-857e-46da-8a48-4d36fe3dbbd7-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-tool-handlers.md create mode 100644 docs/adr/e0d37356-1631-46f3-97d8-1f8d05fd6507-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-nested-field-access.md create mode 100644 docs/adr/e293d8ea-c655-4557-92c6-da3bd24018b1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-implemented.md create mode 100644 docs/adr/e4caeb99-f530-4d0f-baad-a803acfbb9d2-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-modules.md create mode 100644 docs/adr/e555e1eb-f5f2-4d66-ae3c-34b596cf39dc-adopt-model-context-protocol-sdk-for-android-device-integration-type-definitions-imported.md create mode 100644 docs/adr/e58a0565-70ba-4773-89f2-1b12438a06f6-adopt-model-context-protocol-sdk-for-android-device-integration-tool-lookup-use.md create mode 100644 docs/adr/e61011fa-9c21-47e2-bfeb-aa5f1be29b09-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-assignment-logic.md create mode 100644 docs/adr/ea4b543d-d0be-4462-9fa3-fa0b2f2fe57d-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-android-activities-requiring.md create mode 100644 docs/adr/ebc960ca-53bf-4ba9-9e24-ba3551bc90e3-adopt-model-context-protocol-sdk-for-android-device-integration-server-initialization-declare.md create mode 100644 docs/adr/ed0c7f79-7808-4d5a-a55b-ee6ba89ae4d1-enforce-schema-based-input-validation-for-public-api-endpoints-schema-definitions-specify.md create mode 100644 docs/adr/ed5f75c6-3d47-4881-8c46-b0fdccbde759-adopt-hilt-dependency-injection-for-android-application-components-application-class-use.md create mode 100644 docs/adr/f00636db-400f-40df-b081-6340fb4bdaa2-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-test-method-names.md create mode 100644 docs/adr/f02d043d-5823-4aeb-abfe-49a1db7895f6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-utilities-centralized.md create mode 100644 docs/adr/f12fda34-6c1a-45ce-937f-786fd0b3e6af-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-configuration-define-application.md create mode 100644 docs/adr/f2faca50-9c9e-4ea3-95ac-c41b960a4059-standardize-public-contract-functions-for-github-integration-automation-github-integration-scripts.md create mode 100644 docs/adr/f44a5164-24d3-4b66-8385-c0f71dfc3f0b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-automation-scripts-load.md create mode 100644 docs/adr/f5e43e08-8bf6-4b41-a34c-4721ee14a1b4-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md create mode 100644 docs/adr/f8f48f71-1510-4000-84be-9e9f3a16e0d9-adopt-zod-schema-validation-for-tool-input-parameters-tool-implementations-import.md create mode 100644 docs/adr/f91ae19b-2748-445b-8617-0fb6a06e5b19-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-body.md create mode 100644 docs/adr/facaccf3-6586-4106-b5ac-4ada57f5feb2-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-tool-error-logs.md create mode 100644 docs/adr/fc062a0d-97da-44ac-9afe-094108c24e86-standardize-collection-find-pattern-for-in-memory-data-queries-predicate-functions-passed.md create mode 100644 docs/adr/ff882c06-6763-459c-a155-d6ee07394f95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-test-specifications-typescript.md diff --git a/.actual/rules/cross-cutting-activities-extending-componentactivity-7f82.md b/.actual/rules/cross-cutting-activities-extending-componentactivity-7f82.md new file mode 100644 index 00000000000..93b5f6de55f --- /dev/null +++ b/.actual/rules/cross-cutting-activities-extending-componentactivity-7f82.md @@ -0,0 +1,37 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Activities Extending Componentactivity + +These rules are ALWAYS ACTIVE for all Android Activities extending ComponentActivity or AppCompatActivity, Android ViewModels, and the Android Application class within the scope of authentication, autofill, and credential provider flows. + +### Rules + +- **R-HILT-001** SHOULD: Activities extending ComponentActivity or AppCompatActivity SHOULD use @AndroidEntryPoint for lifecycle-aware injection. +- **R-HILT-002** SHOULD: All ViewModel classes requiring dependency injection SHOULD be annotated with @HiltViewModel. +- **R-HILT-003** SHOULD: The Application class SHOULD use @Inject for application-scoped dependencies. +- **R-HILT-004** SHOULD: Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint. +- **R-HILT-005** SHOULD: Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle. +- **R-HILT-006** SHOULD: Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types). + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify @Inject usage in Application class +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence +- Annotation processing completes successfully in CI build pipeline +- No manual dependency construction exists in Android components (Activities, ViewModels, Application) + + +Claude Code MUST NOT skip or defer verification. All Activities, ViewModels, and Application classes in scope MUST be checked for proper Hilt annotations. Build failures from annotation processing errors MUST be resolved before merge. Code review MUST enforce Hilt annotation requirements on new Android components. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-activities-handling-system-ddfe.md b/.actual/rules/cross-cutting-activities-handling-system-ddfe.md new file mode 100644 index 00000000000..b277747b699 --- /dev/null +++ b/.actual/rules/cross-cutting-activities-handling-system-ddfe.md @@ -0,0 +1,42 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Handling System + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ACT-001** MUST: All Activity subclasses serving as application entry points SHALL extend either `androidx.activity.ComponentActivity` or `androidx.appcompat.app.AppCompatActivity`. +- **R-ACT-002** MUST: All Activity classes requiring dependency injection SHALL be annotated with `@AndroidEntryPoint`. +- **R-ACT-003** MUST: All ViewModel classes paired with Activities SHALL be annotated with `@HiltViewModel`. +- **R-ACT-004** MUST: ViewModel instances SHALL be obtained through `androidx.activity.viewModels()` delegation in Activity implementations. +- **R-ACT-005** SHOULD: Activities handling system callbacks SHOULD implement specialized flows for credential provider (CredentialProviderActivity), authentication (AuthCallbackActivity), and autofill (AutofillCallbackActivity) to maintain separation of concerns. +- **R-ACT-006** SHOULD: Intent handling logic SHOULD be implemented in `onCreate` and `onNewIntent` methods, routing Intent data to ViewModel through sealed action classes. +- **R-ACT-007** SHOULD: Activity entry points SHOULD be declared in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes). +- **R-ACT-008** SHOULD: ViewModel implementations SHOULD extend BaseViewModel as common parent class to standardize state management patterns and lifecycle handling. +- **R-ACT-009** MAY: Legacy Activity implementations may temporarily use `android.app.Activity` base class during migration to AndroidX (EXC-001). + +### Verify + +```bash +# Verify Activity base class inheritance +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Verify @AndroidEntryPoint annotation on Activities +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Verify @HiltViewModel annotation on ViewModels +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify androidx.activity.viewModels delegation usage +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either `androidx.activity.ComponentActivity` or `androidx.appcompat.app.AppCompatActivity` +- All Activity classes requiring dependency injection are annotated with `@AndroidEntryPoint` +- All ViewModel classes are annotated with `@HiltViewModel` and obtained through `androidx.activity.viewModels()` delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) +- Activity entry points are declared in AndroidManifest.xml with appropriate intent filters + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for Activity base class inheritance patterns, lint rules checking @AndroidEntryPoint annotation presence, code review verification of ViewModel instantiation, and CI pipeline checks for AndroidManifest Activity declarations are mandatory. Violations result in CI build failure, lint warnings escalated to errors, and code review blocks. Exceptions require architecture team approval and tracking issues with migration plans. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-activities-requiring-dependency-2c48.md b/.actual/rules/cross-cutting-activities-requiring-dependency-2c48.md new file mode 100644 index 00000000000..d773220862d --- /dev/null +++ b/.actual/rules/cross-cutting-activities-requiring-dependency-2c48.md @@ -0,0 +1,42 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Requiring Dependency + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ACTIVITY-001** MUST: Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint to enable Hilt code generation and injection lifecycle. +- **R-ACTIVITY-002** MUST: All Activity classes serving as application entry points MUST extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity. +- **R-ACTIVITY-003** MUST: All ViewModel classes paired with Activities MUST be annotated with @HiltViewModel. +- **R-ACTIVITY-004** MUST: ViewModel instances MUST be obtained through androidx.activity.viewModels() delegation in Activity implementations. +- **R-ACTIVITY-005** MUST: Intent handling MUST be implemented in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes. +- **R-ACTIVITY-006** MUST: Specialized Activity implementations MUST exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI). +- **R-ACTIVITY-007** SHOULD: Activity entry points SHOULD be declared in AndroidManifest.xml with appropriate intent filters for system integration. +- **R-ACTIVITY-008** SHOULD: ViewModels SHOULD extend BaseViewModel as common parent class to standardize state management patterns and lifecycle handling. + +### Verify + +```bash +# Count Activity classes extending approved AndroidX base classes +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count Activity classes annotated with @AndroidEntryPoint +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count ViewModel classes annotated with @HiltViewModel +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Count Activity classes using androidx.activity.viewModels delegation +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) +- Intent handling is implemented in onCreate and onNewIntent methods with routing to ViewModel through sealed action classes +- Activity entry points are declared in AndroidManifest.xml with appropriate intent filters + + +Claude Code MUST NOT skip or defer verification. All Activity and ViewModel implementations MUST comply with R-ACTIVITY-001 through R-ACTIVITY-008. Violations block CI pipeline builds and require architecture team approval for exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-activities-use-androidx-9fdc.md b/.actual/rules/cross-cutting-activities-use-androidx-9fdc.md new file mode 100644 index 00000000000..ae70f4fc15c --- /dev/null +++ b/.actual/rules/cross-cutting-activities-use-androidx-9fdc.md @@ -0,0 +1,33 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Use Androidx + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ACT-001** SHOULD: Activities SHOULD use androidx.activity.viewModels delegation for ViewModel instantiation to ensure proper lifecycle scoping and configuration change survival. + +### Verify + +```bash +# Count Activity classes extending AndroidX base classes +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count Activity classes annotated with @AndroidEntryPoint +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count ViewModel classes annotated with @HiltViewModel +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Count ViewModel instantiations using androidx.activity.viewModels delegation +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for Activity base class inheritance patterns, lint rules checking @AndroidEntryPoint annotation presence, code review verification of ViewModel instantiation, and CI pipeline checks for AndroidManifest Activity declarations are mandatory. Violations result in CI build failure and code review blocks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-activities-use-androidx-c392.md b/.actual/rules/cross-cutting-activities-use-androidx-c392.md new file mode 100644 index 00000000000..bbce6cd991b --- /dev/null +++ b/.actual/rules/cross-cutting-activities-use-androidx-c392.md @@ -0,0 +1,43 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Use Androidx + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ACT-001** MAY: Activities MAY use androidx.activity.result.contract.ActivityResultContracts for type-safe activity result handling when coordinating with other activities or system pickers. +- **R-ACT-002** MUST: All Activity subclasses serving as application entry points MUST extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity. +- **R-ACT-003** MUST: All Activity classes requiring dependency injection MUST be annotated with @AndroidEntryPoint. +- **R-ACT-004** MUST: All ViewModel classes paired with Activities MUST be annotated with @HiltViewModel. +- **R-ACT-005** MUST: ViewModel instances MUST be obtained through androidx.activity.viewModels() delegation in Activity implementations. +- **R-ACT-006** MUST: Intent handling MUST be implemented in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes. +- **R-ACT-007** MUST: Specialized Activity implementations MUST exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI). +- **R-ACT-008** SHOULD: Activity entry points SHOULD be declared in AndroidManifest.xml with appropriate intent filters for system integration. +- **R-ACT-009** SHOULD: ViewModel implementations SHOULD extend BaseViewModel as common parent class to standardize state management patterns and lifecycle handling. + +### Verify + +```bash +# Count Activity classes extending AndroidX base classes +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count Activity classes annotated with @AndroidEntryPoint +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count ViewModel classes annotated with @HiltViewModel +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Count Activity classes using androidx.activity.viewModels delegation +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) +- Intent handling is implemented in onCreate and onNewIntent methods with routing to ViewModel through sealed action classes +- Activity entry points are declared in AndroidManifest.xml with appropriate intent filters + + +Claude Code MUST NOT skip or defer verification. All Activity and ViewModel implementations MUST comply with R-ACT-002 through R-ACT-007 (MUST-level rules). Violations block CI pipeline builds. Exceptions require architecture team approval and tracking issues with migration plans. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-activity-implementations-override-4358.md b/.actual/rules/cross-cutting-activity-implementations-override-4358.md new file mode 100644 index 00000000000..b3b362acd1d --- /dev/null +++ b/.actual/rules/cross-cutting-activity-implementations-override-4358.md @@ -0,0 +1,42 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activity Implementations Override + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ACTIVITY-001** MUST: Activity implementations MUST override onCreate with Bundle parameter and handle Intent routing through android.content.Intent to support system-initiated flows. +- **R-ACTIVITY-002** MUST: All Activity classes requiring dependency injection MUST be annotated with @AndroidEntryPoint to enable Hilt code generation. +- **R-ACTIVITY-003** MUST: All Activity classes MUST extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity as base classes. +- **R-ACTIVITY-004** MUST: All ViewModel classes paired with Activities MUST be annotated with @HiltViewModel. +- **R-ACTIVITY-005** MUST: ViewModel instances MUST be obtained through androidx.activity.viewModels() delegation in Activity onCreate to ensure proper lifecycle scoping. +- **R-ACTIVITY-006** MUST: Intent data routing MUST be implemented in onCreate and onNewIntent methods, delegating to ViewModel through sealed action classes. +- **R-ACTIVITY-007** MUST: All Activity entry points MUST be declared in AndroidManifest.xml with appropriate intent filters for system integration. +- **R-ACTIVITY-008** SHOULD: ViewModel implementations SHOULD extend BaseViewModel as common parent class to standardize state management patterns. + +### Verify + +```bash +# Count Activity classes extending approved AndroidX base classes +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count Activity classes annotated with @AndroidEntryPoint +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count ViewModel classes annotated with @HiltViewModel +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Count Activity classes using androidx.activity.viewModels delegation +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) +- Intent handling is implemented in onCreate and onNewIntent methods with routing to ViewModel +- All Activity entry points are declared in AndroidManifest.xml with appropriate intent filters + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for Activity base class inheritance patterns, lint rules checking @AndroidEntryPoint annotation presence, code review verification of ViewModel instantiation, and CI pipeline checks for AndroidManifest Activity declarations are mandatory. Violations result in CI build failure and code review blocks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-additional-validation-constraints-be5d.md b/.actual/rules/cross-cutting-additional-validation-constraints-be5d.md new file mode 100644 index 00000000000..9bf46903860 --- /dev/null +++ b/.actual/rules/cross-cutting-additional-validation-constraints-be5d.md @@ -0,0 +1,34 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Additional Validation Constraints + +These rules are ALWAYS ACTIVE for all tool handlers in android-device-server, XML parsing operations, GitHub automation scripts, public API contracts, and command-line argument parsing that process external inputs. + +### Rules + +- **R-VAL-001** MAY: Additional validation constraints MAY be applied for domain-specific requirements such as minimum wait times (z.number().min(0)) or path pattern matching. + +### Verify + +```bash +# Verify zod schema adoption in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Verify fast-xml-parser usage in XML parsing operations +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Verify json.load validation in GitHub automation scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation test suite +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML +- Domain-specific constraints (minimum values, pattern matching) are documented in schema definitions + + +Clause Code MUST NOT skip or defer verification of input validation schemas. All external inputs processed by tool handlers, XML parsers, and GitHub automation scripts MUST be validated against defined schemas before use. Pull requests introducing new API endpoints or input processing without schema validation MUST be blocked in code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-android-activities-requiring-ea4b.md b/.actual/rules/cross-cutting-android-activities-requiring-ea4b.md new file mode 100644 index 00000000000..d1dc85d2714 --- /dev/null +++ b/.actual/rules/cross-cutting-android-activities-requiring-ea4b.md @@ -0,0 +1,42 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Android Activities Requiring + +These rules are ALWAYS ACTIVE for all Android Activities, ViewModels, and Application classes requiring dependency injection across authentication, autofill, and credential provider flows. + +### Rules + +- **R-HILT-001** MUST: All Android Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint +- **R-HILT-002** MUST: All Android ViewModels requiring dependency injection MUST be annotated with @HiltViewModel +- **R-HILT-003** MUST: The Application class MUST use @Inject for application-scoped dependencies +- **R-HILT-004** MUST: Activities extending ComponentActivity or AppCompatActivity MUST apply @AndroidEntryPoint before using constructor injection +- **R-HILT-005** SHOULD: Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- **R-HILT-006** SHOULD: Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle +- **R-HILT-007** MUST: Hilt Gradle plugin MUST be configured in app/build.gradle.kts and kapt MUST be applied for annotation processing +- **R-HILT-008** SHOULD: Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify @Inject usage in Application class +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +# Verify Hilt plugin configuration +grep -E "id\(.*hilt.*\)" app/build.gradle.kts +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence +- Hilt Gradle plugin is configured and kapt is enabled in build configuration +- Annotation processing completes successfully in CI build pipeline + + +Claude Code MUST NOT skip or defer verification. All Activities and ViewModels requiring dependency injection MUST be annotated with appropriate Hilt annotations. Build failures from annotation processing errors MUST be resolved before merge. Code review MUST enforce Hilt annotation requirements on new Activities and ViewModels. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-android-activity-components-668b.md b/.actual/rules/cross-cutting-android-activity-components-668b.md new file mode 100644 index 00000000000..72e18ebb1b2 --- /dev/null +++ b/.actual/rules/cross-cutting-android-activity-components-668b.md @@ -0,0 +1,47 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Android Activity Components + +These rules are ALWAYS ACTIVE for all Android Activity components, ViewModel implementations, Application classes, and related dependency injection patterns across the codebase. + +### Rules + +- **R-HILT-001** MUST: All Android Activity components MUST be annotated with @AndroidEntryPoint to enable Hilt dependency injection. +- **R-HILT-002** MUST: All ViewModel classes MUST be annotated with @HiltViewModel and use constructor injection with @Inject for all dependencies. +- **R-HILT-003** MUST: The Application class MUST be annotated with @HiltAndroidApp to initialize the Hilt dependency graph. +- **R-HILT-004** MUST: Activities MUST use androidx.activity.viewModels() delegate to obtain Hilt-injected ViewModels with proper scoping. +- **R-HILT-005** SHOULD: Dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) SHOULD be documented in module provider methods. +- **R-HILT-006** MUST: Manual dependency instantiation in Hilt-enabled components MUST NOT occur; all dependencies MUST be injected. + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count @Inject annotations on constructors and lateinit vars +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +# Verify @HiltAndroidApp on Application class +grep -r '@HiltAndroidApp' app/src/main/kotlin --include='*Application.kt' + +# Check for manual dependency instantiation patterns in Hilt components +grep -r 'new.*Repository\|new.*Manager' app/src/main/kotlin --include='*Activity.kt' --include='*ViewModel.kt' | grep -v '//' || echo 'No manual instantiation detected' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application class is annotated with @HiltAndroidApp +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle +- No manual dependency instantiation patterns detected in Activity or ViewModel classes +- androidx.activity.viewModels() delegate is used in Activities for ViewModel injection + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for Android Activity components and related dependency injection patterns. Violations MUST be caught during code review and CI build verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-android-framework-components-b803.md b/.actual/rules/cross-cutting-android-framework-components-b803.md new file mode 100644 index 00000000000..5d94cdd52dc --- /dev/null +++ b/.actual/rules/cross-cutting-android-framework-components-b803.md @@ -0,0 +1,33 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Android Framework Components + +These rules are ALWAYS ACTIVE for all Android framework components (Activities, Application, ViewModels) and their dependency injection patterns across the codebase. + +### Rules + +- **R-HILT-001** MUST_NOT: Android framework components MUST_NOT manually instantiate dependencies that can be provided through Hilt injection. + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count @Inject annotations on constructors and lateinit vars +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + + +Clause Code MUST NOT skip or defer verification. Static analysis via custom lint rules, code review checklists, CI build verification, and architecture tests are mandatory before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-application-class-use-7fe1.md b/.actual/rules/cross-cutting-application-class-use-7fe1.md new file mode 100644 index 00000000000..f6c88532998 --- /dev/null +++ b/.actual/rules/cross-cutting-application-class-use-7fe1.md @@ -0,0 +1,38 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Application Class Use + +These rules are ALWAYS ACTIVE for all Android Application classes, Activities, ViewModels, and related Android component lifecycle management code within the project. + +### Rules + +- **R-HILT-001** MUST: The Application class MUST use @Inject for field or constructor injection of application-scoped dependencies. +- **R-HILT-002** MUST: All Activity classes requiring dependency injection MUST be annotated with @AndroidEntryPoint. +- **R-HILT-003** MUST: All ViewModel classes requiring dependency injection MUST be annotated with @HiltViewModel. +- **R-HILT-004** SHOULD: Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint. +- **R-HILT-005** SHOULD: Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle. +- **R-HILT-006** SHOULD: Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types). + +### Verify + +```bash +# Verify @AndroidEntryPoint usage on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Verify @HiltViewModel usage on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify @Inject usage in Application class +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence +- Hilt Gradle plugin is configured in app/build.gradle.kts +- kapt is enabled for annotation processing +- No manual dependency construction exists in Android components that should use Hilt + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for Android component lifecycle management code. Violations must be corrected before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-application-class-use-ed5f.md b/.actual/rules/cross-cutting-application-class-use-ed5f.md new file mode 100644 index 00000000000..d480c40d67c --- /dev/null +++ b/.actual/rules/cross-cutting-application-class-use-ed5f.md @@ -0,0 +1,33 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Application Class Use + +These rules are ALWAYS ACTIVE for all Android application components including Activity subclasses, ViewModel implementations, Application class, Repository and Manager classes, and feature modules (authentication, autofill, credential provider). + +### Rules + +- **R-HILT-001** MUST: Application class MUST use @Inject annotation for field injection of application-scoped dependencies + +### Verify + +```bash +# Verify @AndroidEntryPoint usage on Activity classes +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Verify @HiltViewModel usage on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Verify @Inject usage in constructors and field injection +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + + +Claude Code MUST NOT skip or defer verification. Static analysis via custom lint rules, code review checklists, CI build verification, and architecture tests are mandatory. Violations result in CI build failures and code review blocks. Exceptions require explicit approval from tech lead with documented justification and expiration date. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-application-entry-points-442f.md b/.actual/rules/cross-cutting-application-entry-points-442f.md new file mode 100644 index 00000000000..68b809ea751 --- /dev/null +++ b/.actual/rules/cross-cutting-application-entry-points-442f.md @@ -0,0 +1,46 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Application Entry Points + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ENTRY-001** MUST: All application entry points MUST extend either `androidx.activity.ComponentActivity` or `androidx.appcompat.app.AppCompatActivity` to ensure compatibility with AndroidX lifecycle, ViewModel, and Compose integration. + +- **R-ENTRY-002** MUST: All Activity classes requiring dependency injection MUST be annotated with `@AndroidEntryPoint` to enable Hilt dependency injection code generation. + +- **R-ENTRY-003** MUST: All ViewModel classes MUST be annotated with `@HiltViewModel` and obtained through `androidx.activity.viewModels()` delegation in Activity implementations. + +- **R-ENTRY-004** MUST: Specialized Activity implementations MUST exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) with appropriate Intent routing and lifecycle management. + +- **R-ENTRY-005** SHOULD: Extend `androidx.activity.ComponentActivity` for Compose-based Activities or `androidx.appcompat.app.AppCompatActivity` for View-based Activities with AppCompat theme support. + +- **R-ENTRY-006** SHOULD: Implement Intent handling in `onCreate` and `onNewIntent` methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent). + +- **R-ENTRY-007** SHOULD: Use `BaseViewModel` as common parent class for ViewModels to standardize state management patterns and lifecycle handling. + +### Verify + +```bash +# Count Activity classes extending approved AndroidX base classes +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count Activity classes annotated with @AndroidEntryPoint +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count ViewModel classes annotated with @HiltViewModel +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Count Activity classes using androidx.activity.viewModels delegation +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either `androidx.activity.ComponentActivity` or `androidx.appcompat.app.AppCompatActivity` +- All Activity classes requiring dependency injection are annotated with `@AndroidEntryPoint` +- All ViewModel classes are annotated with `@HiltViewModel` and obtained through `androidx.activity.viewModels()` delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) +- AndroidManifest.xml Activity declarations match implementation files with appropriate intent filters + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for Activity base class inheritance patterns, lint rules checking @AndroidEntryPoint annotation presence, code review verification of ViewModel instantiation, and CI pipeline checks for AndroidManifest Activity declarations are mandatory. Violations result in CI build failure and code review blocks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-application-specific-labels-53b2.md b/.actual/rules/cross-cutting-application-specific-labels-53b2.md new file mode 100644 index 00000000000..e782f2eba3e --- /dev/null +++ b/.actual/rules/cross-cutting-application-specific-labels-53b2.md @@ -0,0 +1,38 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Application Specific Labels + +These rules are ALWAYS ACTIVE for GitHub pull request labeling automation scripts and external client boundary interactions requiring label management based on configuration-driven pattern matching. + +### Rules + +- **R-LABEL-001** MAY: Application-specific labels (e.g., app:password-manager, app:authenticator) MAY be added conditionally based on path patterns. +- **R-LABEL-002** MUST: Use set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls to ensure O(1) deduplication and prevent duplicate API calls. +- **R-LABEL-003** MUST: Initialize label sets early in the workflow to ensure all conditional branches can add labels safely. +- **R-LABEL-004** SHOULD: Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels. +- **R-LABEL-005** MUST: Validate JSON configuration schema on load to catch malformed patterns before runtime. +- **R-LABEL-006** SHOULD: Log the final label set before API calls to aid debugging and auditing. +- **R-LABEL-007** MUST: Batch label operations before external API calls to minimize network overhead and API rate limit consumption. +- **R-LABEL-008** SHOULD: Implement configuration validation to detect and warn about overlapping or duplicate patterns. + +### Verify + +```bash +# Detect set-based label accumulation patterns +grep -r '\.add("app:' .github/scripts/ | wc -l + +# Verify set initialization +grep -r 'labels.*=.*set()' .github/scripts/ | wc -l + +# Verify Python syntax +python3 -m py_compile .github/scripts/label-pr.py +``` + +**Accept when:** +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation +- JSON configuration schema validation is implemented around json.load() calls +- Label sets are initialized before conditional branches that add labels + + +Claude Code MUST NOT skip or defer verification. All set-based label accumulation patterns MUST be validated before approving pull request labeling automation scripts. Configuration parsing errors MUST be handled with try-except blocks and fallback behavior. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-asynchronous-operations-execute-34bb.md b/.actual/rules/cross-cutting-asynchronous-operations-execute-34bb.md new file mode 100644 index 00000000000..864977dcb93 --- /dev/null +++ b/.actual/rules/cross-cutting-asynchronous-operations-execute-34bb.md @@ -0,0 +1,33 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Asynchronous Operations Execute + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the codebase that manage UI state through Hilt dependency injection and MutableStateFlow patterns. + +### Rules + +- **R-ASYNC-001** MUST: Asynchronous operations MUST execute within viewModelScope to ensure proper lifecycle management and cancellation. + +### Verify + +```bash +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages for state mutations +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages for async operations +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + + +Clause Code MUST NOT skip or defer verification of R-ASYNC-001 compliance. All asynchronous operations in ViewModels must be scoped to viewModelScope to guarantee proper cancellation and lifecycle alignment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-automation-scripts-load-f44a.md b/.actual/rules/cross-cutting-automation-scripts-load-f44a.md new file mode 100644 index 00000000000..93d0a06446c --- /dev/null +++ b/.actual/rules/cross-cutting-automation-scripts-load-f44a.md @@ -0,0 +1,43 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Automation Scripts Load + +These rules are ALWAYS ACTIVE for PR automation scripts in the `.github/scripts/` directory that process pull requests through pattern-based label assignment, particularly `label-pr.py` and related configuration-driven labeling workflows. + +### Rules + +- **R-AUTOMATION-001** MUST: PR automation scripts MUST load label classification rules from JSON configuration files using `json.load` to enable data-driven pattern matching. +- **R-AUTOMATION-002** MUST: All GitHub API interactions MUST be encapsulated in dedicated functions with `gh_` prefix (e.g., `gh_get_changed_files`, `gh_get_pr_title`, `gh_add_labels`, `gh_replace_labels`). +- **R-AUTOMATION-003** MUST: Label assignment logic MUST evaluate both `title_patterns` and `path_patterns` from configuration to determine label application. +- **R-AUTOMATION-004** MUST: JSON configuration parsing MUST include exception handling for `json.JSONDecodeError` to handle malformed configuration gracefully. +- **R-AUTOMATION-005** SHOULD: PR automation scripts SHOULD use Python sets for label collection to automatically deduplicate labels before applying to PR. +- **R-AUTOMATION-006** SHOULD: Logging statements SHOULD be added at key decision points (pattern matches, label additions) to enable debugging and audit trail. +- **R-AUTOMATION-007** SHOULD: Dry-run mode SHOULD be implemented for testing pattern changes and maintaining audit logs of label assignments with pattern match details. + +### Verify + +```bash +# Verify json.load usage in label-pr.py +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions exist +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +# Verify JSON exception handling +grep -E 'except.*json|JSONDecodeError' .github/scripts/label-pr.py + +# Verify pattern evaluation logic +grep -E '(title_patterns|path_patterns)' .github/scripts/label-pr.py +``` + +**Accept when:** +- The `label-pr.py` script successfully loads JSON configuration and contains exception handling for JSON parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with `gh_` prefix +- The script evaluates both `title_patterns` and `path_patterns` from configuration to determine label assignment +- Python syntax validation passes without errors +- Configuration-driven pattern matching is the primary mechanism for label assignment + + +Claude Code MUST NOT skip or defer verification of these rules. All R-AUTOMATION rules must be validated before accepting changes to PR automation scripts. Violations of MUST-level rules block PR automation workflow execution. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-avoid-manual-iteration-1ba7.md b/.actual/rules/cross-cutting-avoid-manual-iteration-1ba7.md new file mode 100644 index 00000000000..150407ea44c --- /dev/null +++ b/.actual/rules/cross-cutting-avoid-manual-iteration-1ba7.md @@ -0,0 +1,29 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Avoid Manual Iteration + +These rules are ALWAYS ACTIVE for all TypeScript, JavaScript, and Python files performing in-memory data queries, particularly when working with parsed system output, configuration data, and test fixtures. + +### Rules + +- **R-COLL-001** SHOULD_NOT: Avoid manual iteration with for-loops when Array.find() or Set operations provide equivalent functionality with clearer intent. + +### Verify + +```bash +# Verify Array.find() usage with predicate functions in TypeScript/JavaScript +grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . + +# Verify Set.add() usage for collection building in Python +grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' + +# Verify test suite passes with window lookup operations +npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' +``` + +**Accept when:** +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + + +Clause Code MUST NOT skip or defer verification. All three verification commands must pass before accepting changes that introduce or modify collection query patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-boolean-flag-parameters-2f3c.md b/.actual/rules/cross-cutting-boolean-flag-parameters-2f3c.md new file mode 100644 index 00000000000..a976e024bbf --- /dev/null +++ b/.actual/rules/cross-cutting-boolean-flag-parameters-2f3c.md @@ -0,0 +1,30 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Boolean Flag Parameters + +These rules are ALWAYS ACTIVE for all tool handler implementations in `src/tools/` that accept external input parameters. + +### Rules + +- **R-ZOD-001** SHOULD: Boolean flag parameters SHOULD use `z.boolean().optional().default()` to provide sensible defaults. + +### Verify + +```bash +# Verify Zod imports are present in tool handlers +grep -r "from 'zod'" src/tools/ | wc -l + +# Verify z.object() schema definitions are used +grep -r "z\.object({" src/tools/ | wc -l + +# Verify validation utility imports are present +grep -r "../utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool handlers in `src/tools/` that accept external parameters import `zod` and define validation schemas +- Grep commands show consistent usage of `z.object()` schema definitions across tool implementations +- Validation utility imports from `../utils/validation.js` are present in all relevant tool files +- Boolean flag parameters use `.optional().default()` pattern for sensible defaults + + +Clause Code MUST NOT skip or defer verification. All tool handlers accepting external parameters MUST conform to this schema validation pattern. Violations are treated as code review blockers and CI pipeline failures. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-component-functions-that-68f3.md b/.actual/rules/cross-cutting-component-functions-that-68f3.md new file mode 100644 index 00000000000..a178544b093 --- /dev/null +++ b/.actual/rules/cross-cutting-component-functions-that-68f3.md @@ -0,0 +1,35 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Component Functions That + +These rules are ALWAYS ACTIVE for all Android UI component functions in app/src/main/kotlin UI packages, authentication feature module UI components, and any function that directly or indirectly emits Compose UI elements. + +### Rules + +- **R-COMPOSE-001** MUST: All UI component functions that emit visual elements MUST be annotated with @Composable from androidx.compose.runtime. +- **R-COMPOSE-002** MUST: Import androidx.compose.runtime.Composable explicitly in all UI component files. +- **R-COMPOSE-003** SHOULD: Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives. +- **R-COMPOSE-004** SHOULD: Integrate androidx.compose.runtime.remember for state that should survive recomposition. +- **R-COMPOSE-005** SHOULD: Follow naming convention of PascalCase for Composable functions to distinguish from regular functions. +- **R-COMPOSE-006** SHOULD: Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries. + +### Verify + +```bash +# Count @Composable annotations in UI packages +grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Count explicit imports of Composable annotation +grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Find UI screen files missing @Composable annotation +find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation +- All UI component files contain explicit imports of androidx.compose.runtime.Composable + + +Claude Code MUST NOT skip or defer verification. Build failure occurs if Composable functions violate compiler constraints. Code review rejection required for UI functions missing @Composable annotation. Automated linting warnings flag missing androidx.compose.runtime.Composable imports. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-components-use-inject-243c.md b/.actual/rules/cross-cutting-components-use-inject-243c.md new file mode 100644 index 00000000000..8f82972a180 --- /dev/null +++ b/.actual/rules/cross-cutting-components-use-inject-243c.md @@ -0,0 +1,31 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Components Use Inject + +These rules are ALWAYS ACTIVE for all Android Activities, ViewModels, and Application classes requiring dependency injection across authentication, autofill, and credential provider flows. + +### Rules + +- **R-HILT-001** MAY: Components MAY use @Inject for field injection when constructor injection is not feasible + +### Verify + +```bash +# Verify @AndroidEntryPoint annotations on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Verify @HiltViewModel annotations on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify @Inject usage in Application class +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence +- Annotation processing completes successfully during CI build pipeline validation + + +Claude Code MUST NOT skip or defer verification. All Activities, ViewModels, and Application classes must comply with Hilt annotation requirements before code review approval. Build failures from annotation processing errors must be resolved before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-composable-files-import-341a.md b/.actual/rules/cross-cutting-composable-files-import-341a.md new file mode 100644 index 00000000000..1f6bc42711f --- /dev/null +++ b/.actual/rules/cross-cutting-composable-files-import-341a.md @@ -0,0 +1,30 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Composable Files Import + +These rules are ALWAYS ACTIVE for all Android UI screen implementations in app/src/main/kotlin UI packages, authentication feature module UI components, and any function that directly or indirectly emits Compose UI elements. + +### Rules + +- **R-COMPOSE-001** MUST: Composable UI files MUST import androidx.compose.runtime.Composable explicitly rather than relying on wildcard imports. + +### Verify + +```bash +# Count total @Composable annotations in UI packages +grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Count explicit imports of androidx.compose.runtime.Composable +grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Find UI component files missing @Composable annotation +find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation +- Explicit imports of androidx.compose.runtime.Composable are present in all Composable UI files + + +Claude Code MUST NOT skip or defer verification. Build failure occurs if Composable functions violate compiler constraints. Code review rejection is required for UI functions missing @Composable annotation. Automated linting warnings flag missing androidx.compose.runtime.Composable imports. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-composable-functions-integrate-9d19.md b/.actual/rules/cross-cutting-composable-functions-integrate-9d19.md new file mode 100644 index 00000000000..85b0df41c05 --- /dev/null +++ b/.actual/rules/cross-cutting-composable-functions-integrate-9d19.md @@ -0,0 +1,29 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Composable Functions Integrate + +These rules are ALWAYS ACTIVE for all UI screens in the app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy, authentication feature screens, handlers, and new screen implementations across all feature modules. + +### Rules + +- **R-COMPOSE-001** MUST: Composable functions MUST integrate with androidx.compose.runtime utilities (remember, Composable annotation) for state management. + +### Verify + +```bash +# Count @Composable annotations in UI module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout component usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + + +Clause Code MUST NOT skip or defer verification. CI pipeline grep checks for @Composable annotation presence in *Screen.kt files are mandatory. Code review checklist verification of Compose usage in new UI implementations is required. Static analysis rules detecting XML layout inflation in new feature modules must pass. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-composable-functions-use-42ea.md b/.actual/rules/cross-cutting-composable-functions-use-42ea.md new file mode 100644 index 00000000000..53d7a65209f --- /dev/null +++ b/.actual/rules/cross-cutting-composable-functions-use-42ea.md @@ -0,0 +1,30 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Composable Functions Use + +These rules are ALWAYS ACTIVE for all Android UI screen implementations in app/src/main/kotlin UI packages, authentication feature module UI components, and any function that directly or indirectly emits Compose UI elements. + +### Rules + +- **R-COMPOSE-001** SHOULD: Composable functions SHOULD use androidx.compose.runtime.remember for state preservation across recompositions. + +### Verify + +```bash +# Count @Composable annotations in UI packages +grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Verify explicit imports of Composable annotation +grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Find UI screen files missing @Composable annotation +find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files) +- No UI component files emit visual elements without @Composable annotation +- androidx.compose.runtime.Composable is explicitly imported in all UI component files + + +Claude Code MUST NOT skip or defer verification. Automated static analysis via Compose compiler checks during build is mandatory. Code review checklist must require @Composable annotation for UI functions. CI pipeline grep verification must count @Composable usage in UI packages. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-composable-functions-use-f5e4.md b/.actual/rules/cross-cutting-composable-functions-use-f5e4.md new file mode 100644 index 00000000000..15381a23dcd --- /dev/null +++ b/.actual/rules/cross-cutting-composable-functions-use-f5e4.md @@ -0,0 +1,36 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Composable Functions Use + +These rules are ALWAYS ACTIVE for all Android UI screen implementations in `app/src/main/kotlin` UI packages, authentication feature module UI components, and any function that directly or indirectly emits Compose UI elements. + +### Rules + +- **R-COMPOSE-001** MUST: All UI screen implementations and handler components that emit Compose UI elements SHALL be annotated with `@Composable`. +- **R-COMPOSE-002** MUST: Import `androidx.compose.runtime.Composable` explicitly in all UI component files that declare composable functions. +- **R-COMPOSE-003** SHOULD: Use `androidx.compose.foundation.layout` components (Column, Row, Spacer, Box) as primary layout primitives for UI composition. +- **R-COMPOSE-004** SHOULD: Integrate `androidx.compose.runtime.remember` for state that should survive recomposition cycles. +- **R-COMPOSE-005** SHOULD: Follow PascalCase naming convention for Composable functions to distinguish them from regular functions. +- **R-COMPOSE-006** SHOULD: Maintain clear architectural boundaries by separating Composable UI functions from ViewModel and business logic layers. +- **R-COMPOSE-007** MAY: Composable functions MAY use `androidx.activity.compose` utilities (e.g., BackHandler) for platform integration when appropriate. + +### Verify + +```bash +# Count @Composable annotations in UI packages +grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Count explicit imports of androidx.compose.runtime.Composable +grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Find UI screen files missing @Composable annotation +find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All UI screen files (matching `*Screen.kt` pattern) contain at least one `@Composable` annotated function +- Grep for `@Composable` annotation returns matches proportional to UI component count (minimum 3 files as baseline evidence) +- No UI component files emit visual elements without `@Composable` annotation +- All files declaring composable functions explicitly import `androidx.compose.runtime.Composable` + + +Claude Code MUST NOT skip or defer verification of @Composable annotation presence and proper imports in UI component files. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-composables-use-androidx-4aea.md b/.actual/rules/cross-cutting-composables-use-androidx-4aea.md new file mode 100644 index 00000000000..a094d9d017e --- /dev/null +++ b/.actual/rules/cross-cutting-composables-use-androidx-4aea.md @@ -0,0 +1,34 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Composables Use Androidx + +These rules are ALWAYS ACTIVE for all UI screens in the app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy, authentication feature screens, handlers, and new screen implementations across all feature modules. + +### Rules + +- **R-COMPOSE-001** SHOULD: Composables SHOULD use androidx.compose.foundation.Image for image rendering within the composition hierarchy. +- **R-COMPOSE-002** SHOULD: Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required. +- **R-COMPOSE-003** SHOULD: Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic. +- **R-COMPOSE-004** SHOULD: Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes. +- **R-COMPOSE-005** SHOULD: Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates. +- **R-COMPOSE-006** SHOULD: Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens. + +### Verify + +```bash +# Count @Composable annotations in UI module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout component usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + + +Claude Code MUST NOT skip or defer verification. All new UI screen implementations MUST be verified against these rules before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-composables-use-columnscope-4c90.md b/.actual/rules/cross-cutting-composables-use-columnscope-4c90.md new file mode 100644 index 00000000000..03ecad6926a --- /dev/null +++ b/.actual/rules/cross-cutting-composables-use-columnscope-4c90.md @@ -0,0 +1,36 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Composables Use Columnscope + +These rules are ALWAYS ACTIVE for all UI screens in the app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy, authentication feature screens, handlers, and new screen implementations across all feature modules. + +### Rules + +- **R-COMPOSE-001** MAY: Composables MAY use ColumnScope and other scope-specific APIs for context-aware layout composition. +- **R-COMPOSE-002** MUST: All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function. +- **R-COMPOSE-003** MUST: Layout composition use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required. +- **R-COMPOSE-004** SHOULD: Separate screen composables from handler composables to maintain clear separation between UI composition and event handling logic. +- **R-COMPOSE-005** SHOULD: Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes. +- **R-COMPOSE-006** SHOULD: Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates. +- **R-COMPOSE-007** SHOULD: Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens. +- **R-COMPOSE-008** MUST NOT: Create new XML layout files in feature modules covered by this ADR scope. + +### Verify + +```bash +# Count @Composable annotations in UI module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + + +Claude Code MUST NOT skip or defer verification. CI build warnings are generated for new screen files without @Composable annotations. Code review rejection occurs for XML-based layouts in new feature development. Architecture review is required for exception requests with documented justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-configuration-define-application-f12f.md b/.actual/rules/cross-cutting-configuration-define-application-f12f.md new file mode 100644 index 00000000000..a2d257d7616 --- /dev/null +++ b/.actual/rules/cross-cutting-configuration-define-application-f12f.md @@ -0,0 +1,44 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Configuration Define Application + +These rules are ALWAYS ACTIVE for all PR automation scripts in the `.github/scripts/` directory, JSON configuration files defining title_patterns and path_patterns, GitHub API wrapper functions, and CI/CD workflows that trigger PR labeling automation. + +### Rules + +- **R-LABEL-001** MUST: Configuration MUST define application-specific labels (e.g., 'app:password-manager', 'app:authenticator') to enable component-level change tracking. +- **R-LABEL-002** MUST: All GitHub API interactions MUST be encapsulated in dedicated functions with `gh_` prefix (e.g., `gh_get_changed_files`, `gh_get_pr_title`, `gh_add_labels`, `gh_replace_labels`). +- **R-LABEL-003** MUST: Label assignment logic MUST evaluate both `title_patterns` and `path_patterns` from configuration to determine label application. +- **R-LABEL-004** MUST: JSON configuration loading MUST include exception handling for `json.JSONDecodeError` to handle malformed configuration gracefully. +- **R-LABEL-005** SHOULD: Pattern matching logic SHOULD use Python sets for label collection to automatically deduplicate labels before applying to PR. +- **R-LABEL-006** SHOULD: Logging statements SHOULD be added at key decision points (pattern matches, label additions) to enable debugging and audit trail. +- **R-LABEL-007** SHOULD: A dry-run mode SHOULD be implemented for testing pattern changes and maintaining audit logs of label assignments with pattern match details. +- **R-LABEL-008** MAY: Retry logic with exponential backoff MAY be implemented for GitHub API interactions to handle rate limiting and authentication failures. + +### Verify + +```bash +# Verify JSON configuration loading with exception handling +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions exist +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +# Verify JSON schema validation for configuration +grep -E '(title_patterns|path_patterns)' .github/scripts/label-pr.py + +# Verify exception handling for JSON parsing +grep -A 5 'json.load' .github/scripts/label-pr.py | grep -E '(except|JSONDecodeError)' +``` + +**Accept when:** +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with `gh_` prefix +- The script evaluates both `title_patterns` and `path_patterns` from configuration to determine label assignment +- Configuration defines application-specific labels for component-level change tracking +- Python syntax validation passes without errors + + +Claude Code MUST NOT skip or defer verification. All verify commands MUST execute successfully before accepting changes to PR automation scripts or configuration files. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-configuration-loading-functions-1ecc.md b/.actual/rules/cross-cutting-configuration-loading-functions-1ecc.md new file mode 100644 index 00000000000..72581f0ce58 --- /dev/null +++ b/.actual/rules/cross-cutting-configuration-loading-functions-1ecc.md @@ -0,0 +1,40 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Configuration Loading Functions + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that implement GitHub integration automation, particularly those handling configuration loading, GitHub API interactions via subprocess, and label manipulation. + +### Rules + +- **R-GHINT-001** MUST: All GitHub API interaction functions SHALL be prefixed with `gh_` to clearly mark the integration boundary and distinguish from internal helper functions. +- **R-GHINT-002** MUST: Configuration loading functions SHALL validate input data structure including required keys (`title_patterns`, `path_patterns`) before returning to callers. +- **R-GHINT-003** MUST: All JSON parsing in configuration loading functions SHALL include explicit exception handling for `json.JSONDecodeError` with clear error messages. +- **R-GHINT-004** MUST: GitHub API interactions SHALL use subprocess invocation of `gh` CLI rather than direct HTTP client libraries. +- **R-GHINT-005** MUST: Subprocess calls to `gh` CLI SHALL capture both stdout and stderr, logging errors with context about which command failed. +- **R-GHINT-006** SHOULD: Label manipulation SHALL use Python sets for deduplication, converting to lists only when calling `gh` CLI commands. +- **R-GHINT-007** SHOULD: Configuration loading functions SHOULD provide clear error messages when required keys are missing or validation fails. + +### Verify + +```bash +# Verify GitHub integration function naming conventions +grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py + +# Verify JSON parsing includes explicit exception handling +grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py + +# Verify subprocess invocation of gh CLI +grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +# Verify no direct HTTP client library usage for GitHub API +grep -vE '(PyGithub|github3|requests.*api\.github)' .github/scripts/*.py +``` + +**Accept when:** +- All GitHub integration functions follow naming convention (`load_config_json`, `gh_*`) and are discoverable via grep +- JSON parsing includes explicit exception handling for `JSONDecodeError` in configuration loading functions +- GitHub API interactions use subprocess invocation of `gh` CLI rather than direct HTTP client libraries +- Configuration validation explicitly checks for required keys (`title_patterns`, `path_patterns`) before returning +- Subprocess calls capture and log both stdout and stderr with contextual information + + +Claude Code MUST NOT skip or defer verification of these rules. All GitHub integration functions in `.github/scripts/` MUST conform to the naming conventions, error handling patterns, and subprocess-based gh CLI invocation requirements before code is considered complete. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-configuration-parsers-use-c30b.md b/.actual/rules/cross-cutting-configuration-parsers-use-c30b.md new file mode 100644 index 00000000000..c390925365a --- /dev/null +++ b/.actual/rules/cross-cutting-configuration-parsers-use-c30b.md @@ -0,0 +1,38 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Configuration Parsers Use + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON configuration, use argparse for command-line argument handling, or interact with external APIs and systems. + +### Rules + +- **R-CFGPARSE-001** MUST: Configuration parsers MUST use safe dictionary access methods (.get() with defaults or explicit key existence checks) when extracting values from parsed JSON structures. +- **R-CFGPARSE-002** MUST: All json.load() calls MUST be wrapped in try-except blocks with specific exception handling for JSONDecodeError to provide clear error messages. +- **R-CFGPARSE-003** MUST: Scripts accepting command-line arguments MUST use argparse or equivalent structured parsing libraries instead of direct sys.argv parsing. +- **R-CFGPARSE-004** SHOULD: Configuration schemas SHOULD be documented in script docstrings or adjacent README files to guide validation implementation. + +### Verify + +```bash +# Check for json.load calls without try-except blocks +grep -r 'json\.load' .github/scripts/ | while read line; do + file=$(echo "$line" | cut -d: -f1) + if ! grep -q "try:" "$file"; then + echo "Missing exception handling: $file" + fi +done + +# Check for unsafe dictionary access (direct bracket notation without .get()) +grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 + +# Verify argparse usage in scripts with command-line arguments +find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l +``` + +**Accept when:** +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries +- Configuration schemas are documented in script docstrings or README files + + +Claude Code MUST NOT skip or defer verification of these rules. All configuration parser scripts MUST comply with R-CFGPARSE-001 through R-CFGPARSE-003 before approval. Violations require code review feedback and security review for scripts interacting with external systems. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-configuration-pattern-matching-2518.md b/.actual/rules/cross-cutting-configuration-pattern-matching-2518.md new file mode 100644 index 00000000000..504302ce35a --- /dev/null +++ b/.actual/rules/cross-cutting-configuration-pattern-matching-2518.md @@ -0,0 +1,46 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Configuration Pattern Matching + +These rules are ALWAYS ACTIVE for GitHub pull request labeling automation scripts and external client boundary interactions requiring label management based on configuration-driven pattern matching. + +### Rules + +- **R-LABEL-001** SHOULD: Configuration for pattern matching SHOULD be loaded from JSON files using security-validated input parsing. +- **R-LABEL-002** MUST: Use set-based operations (.add, in-membership checks) to accumulate labels before applying them via external API calls. +- **R-LABEL-003** MUST: Initialize label sets early in the workflow to ensure all conditional branches can add labels safely. +- **R-LABEL-004** SHOULD: Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels. +- **R-LABEL-005** MUST: Validate JSON configuration schema on load to catch malformed patterns before runtime. +- **R-LABEL-006** SHOULD: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting. +- **R-LABEL-007** SHOULD: Log the final label set before API calls to aid debugging and auditing. +- **R-LABEL-008** MUST: Batch label operations before external API calls to minimize network overhead and API rate limit consumption. +- **R-LABEL-009** SHOULD: Add configuration validation to detect and warn about overlapping or duplicate patterns. + +### Verify + +```bash +# Detect set-based label accumulation patterns +grep -r '\.add("app:' .github/scripts/ | wc -l + +# Verify set initialization +grep -r 'labels.*=.*set()' .github/scripts/ | wc -l + +# Verify Python syntax +python3 -m py_compile .github/scripts/label-pr.py + +# Check for JSON configuration loading +grep -r 'json\.load' .github/scripts/ | wc -l + +# Verify pattern matching precedes label addition +grep -B5 '\.add(' .github/scripts/label-pr.py | grep -E '(title_patterns|path_patterns)' +``` + +**Accept when:** +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation +- JSON configuration is loaded with error handling (try-except blocks) +- Label sets are initialized before conditional branches that add labels +- Descriptive variable names distinguish accumulated sets from applied labels + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for pull request labeling automation scripts. Violations must be addressed through code review feedback requesting refactoring to the set-based approach, or documented exceptions must be approved by the platform engineering team with inline comments explaining the deviation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-exception-bitwardenerror-198d.md b/.actual/rules/cross-cutting-custom-exception-bitwardenerror-198d.md new file mode 100644 index 00000000000..4207cd274a5 --- /dev/null +++ b/.actual/rules/cross-cutting-custom-exception-bitwardenerror-198d.md @@ -0,0 +1,36 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Custom Exception Bitwardenerror + +These rules are ALWAYS ACTIVE for all network layer unit tests in `network/src/test/kotlin/**/*Test.kt` that validate custom exception to BitwardenError transformations, error response parsing, and HTTP error mocking. + +### Rules + +- **R-BITWARDEN-001** MUST: Custom exception to BitwardenError transformations MUST be tested with JUnit 5 @Test methods that validate both error type and HTTP status code. +- **R-BITWARDEN-002** MUST: Use Response.error() and ResponseBody.toResponseBody() for creating mock HTTP error responses in unit tests. +- **R-BITWARDEN-003** MUST: Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions. +- **R-BITWARDEN-004** MUST: Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites. +- **R-BITWARDEN-005** SHOULD: Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability. +- **R-BITWARDEN-006** SHOULD: Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic). +- **R-BITWARDEN-007** SHOULD: Validate both message and validationErrors fields when testing error parsing logic with assertEquals assertions. + +### Verify + +```bash +# Count Response.error() usage in test files +grep -r "Response.error" network/src/test/kotlin/ | wc -l + +# Count @Test methods validating BitwardenError or Exception transformations +grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l + +# Count assertEquals/assertTrue assertions in error-related test files +grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l +``` + +**Accept when:** +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types (CookieRedirectException, LocalNetworkAccessException) have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields +- Test methods follow arrange-act-assert structure with clear separation of concerns + + +Claude Code MUST NOT skip or defer verification. All new exception types added to the codebase MUST have corresponding @Test methods validating their transformation to BitwardenError. Pull requests adding error handling without tests MUST be blocked until tests are added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-kotlinx-serialization-7733.md b/.actual/rules/cross-cutting-custom-kotlinx-serialization-7733.md new file mode 100644 index 00000000000..77662e3ec9b --- /dev/null +++ b/.actual/rules/cross-cutting-custom-kotlinx-serialization-7733.md @@ -0,0 +1,36 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Custom Kotlinx Serialization + +These rules are ALWAYS ACTIVE for all custom kotlinx.serialization serializers, extension functions converting between domain models and SDK types, and JSON encoding/decoding at service and module boundaries. + +### Rules + +- **R-KSER-001** MUST: All custom kotlinx.serialization serializers MUST have corresponding test classes that verify JSON encoding produces expected structure. +- **R-KSER-002** MUST: Serialization tests MUST use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings. +- **R-KSER-003** MUST: Tests for versioned schemas MUST validate type discriminator field values in separate test methods for each version. +- **R-KSER-004** MUST: Extension function tests (e.g., toSdkPolicyViews) MUST cover edge cases including empty lists and multi-item conversion scenarios. +- **R-KSER-005** SHOULD: Mock factory functions SHOULD be extracted to shared test utilities for reuse across test classes. +- **R-KSER-006** SHOULD: JSON comparison SHOULD ignore property order to avoid brittle tests breaking on benign formatting changes. + +### Verify + +```bash +# Count @Test methods in serializer test files +grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l + +# Count buildJsonObject + assertEquals patterns in serialization tests +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l + +# Find all serializer and extension test files using kotlinx.serialization +find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' +``` + +**Accept when:** +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases +- Mock factory functions are centralized in shared test utilities where applicable + + +Claude Code MUST NOT skip or defer verification. Pull requests adding serializers without tests MUST be blocked in code review. Coverage reports MUST flag untested serialization code for remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dependencies-injected-activities-aa04.md b/.actual/rules/cross-cutting-dependencies-injected-activities-aa04.md new file mode 100644 index 00000000000..404813cd929 --- /dev/null +++ b/.actual/rules/cross-cutting-dependencies-injected-activities-aa04.md @@ -0,0 +1,39 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Dependencies Injected Activities + +These rules are ALWAYS ACTIVE for all Activity subclasses, ViewModel implementations, Application classes, Repository and Manager classes, and feature modules (authentication, autofill, credential provider) within the Android application codebase. + +### Rules + +- **R-HILT-001** SHOULD: Dependencies injected into Activities SHOULD use @Inject annotation for field injection rather than constructor injection. +- **R-HILT-002** MUST: All Activity classes MUST be annotated with @AndroidEntryPoint to enable Hilt dependency injection. +- **R-HILT-003** MUST: All ViewModel classes MUST be annotated with @HiltViewModel and use constructor injection with @Inject for all dependencies. +- **R-HILT-004** MUST: The Application class MUST be annotated with @HiltAndroidApp to initialize the Hilt dependency graph. +- **R-HILT-005** SHOULD: Activities SHOULD use androidx.activity.viewModels() delegate to obtain Hilt-injected ViewModels with proper scoping. +- **R-HILT-006** SHOULD: Dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) SHOULD be documented in module provider methods. + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count @Inject annotations on constructor or field injection +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle +- No manual dependency instantiation exists in Hilt-enabled components + + +Clause Code MUST NOT skip or defer verification. Static analysis via custom lint rules, code review checklists, CI build verification, and architecture tests are mandatory. Violations result in CI build failures and code review blocks. Exceptions require explicit approval from tech lead with documented justification and expiration date. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dependencies-injected-android-77ba.md b/.actual/rules/cross-cutting-dependencies-injected-android-77ba.md new file mode 100644 index 00000000000..6ebc64e4da0 --- /dev/null +++ b/.actual/rules/cross-cutting-dependencies-injected-android-77ba.md @@ -0,0 +1,46 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Dependencies Injected Android + +These rules are ALWAYS ACTIVE for all Android Activities, ViewModels, and Application classes that require dependency injection across authentication, autofill, and credential provider flows. + +### Rules + +- **R-HILT-001** MUST: Dependencies injected into Android components MUST be provided through Hilt modules or constructor injection. +- **R-HILT-002** MUST: All Activity classes requiring dependency injection MUST be annotated with @AndroidEntryPoint. +- **R-HILT-003** MUST: All ViewModel classes requiring dependency injection MUST be annotated with @HiltViewModel. +- **R-HILT-004** MUST: The Application class MUST use @Inject for application-scoped dependencies. +- **R-HILT-005** SHOULD: Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint. +- **R-HILT-006** SHOULD: Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle. +- **R-HILT-007** MUST: Hilt Gradle plugin MUST be configured in app/build.gradle.kts and kapt MUST be applied for annotation processing. +- **R-HILT-008** SHOULD: Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types). + +### Verify + +```bash +# Verify @AndroidEntryPoint annotations on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Verify @HiltViewModel annotations on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify @Inject usage in Application class +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +# Verify Hilt Gradle plugin configuration +grep -E "id\(.*hilt.*\)" app/build.gradle.kts + +# Verify kapt configuration +grep -E "kapt|kotlin-kapt" app/build.gradle.kts +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Hilt Gradle plugin is configured in app/build.gradle.kts +- kapt is enabled for annotation processing +- Verification commands return non-zero counts indicating Hilt annotation presence +- Build completes successfully with no annotation processing errors + + +Claude Code MUST NOT skip or defer verification. All verification commands MUST execute successfully before accepting changes to Android components requiring dependency injection. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dependency-injection-used-34c6.md b/.actual/rules/cross-cutting-dependency-injection-used-34c6.md new file mode 100644 index 00000000000..fa151b32473 --- /dev/null +++ b/.actual/rules/cross-cutting-dependency-injection-used-34c6.md @@ -0,0 +1,33 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Dependency Injection Used + +These rules are ALWAYS ACTIVE for all Android application components including Activity subclasses, ViewModel implementations, Application class, Repository and Manager classes, and feature modules (authentication, autofill, credential provider). + +### Rules + +- **R-DI-001** SHOULD: Dependency injection SHOULD be used for repositories, managers, and platform services across all feature modules. + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count @Inject annotations on constructors and lateinit vars +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + + +Clause Code MUST NOT skip or defer verification. Static analysis via custom lint rules, code review checklists, CI build verification, and architecture tests are mandatory. Violations result in CI build failures, code review blocks, and architecture test failures preventing staging deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dialog-loading-states-c091.md b/.actual/rules/cross-cutting-dialog-loading-states-c091.md new file mode 100644 index 00000000000..396921cebb2 --- /dev/null +++ b/.actual/rules/cross-cutting-dialog-loading-states-c091.md @@ -0,0 +1,40 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Dialog Loading States + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the app module, particularly those managing UI state for authentication flows, application-level state coordination, and dialog/loading state management. + +### Rules + +- **R-HILT-VM-001** SHOULD: Dialog and loading states SHOULD be modeled as sealed classes within the state object to enable exhaustive when expressions. +- **R-HILT-VM-002** MUST: Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor. +- **R-HILT-VM-003** MUST: Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs. +- **R-HILT-VM-004** MUST: Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity and prevent direct value assignments. +- **R-HILT-VM-005** MUST: Launch coroutines within viewModelScope for asynchronous operations; update state in response to results. +- **R-HILT-VM-006** MUST: Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations. +- **R-HILT-VM-007** SHOULD: Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values. + +### Verify + +```bash +# Count @HiltViewModel annotations +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management +- Dialog and loading states are modeled as sealed classes enabling exhaustive when expressions + + +Clause Code MUST NOT skip or defer verification. Violations detected by static analysis rules or code review must be addressed before merge. CI pipeline checks for @HiltViewModel annotation presence are mandatory. Architecture team approval is required for documented exceptions (EXC-001, EXC-002). + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-handling-distinguish-d0fc.md b/.actual/rules/cross-cutting-error-handling-distinguish-d0fc.md new file mode 100644 index 00000000000..7d90e8c92b2 --- /dev/null +++ b/.actual/rules/cross-cutting-error-handling-distinguish-d0fc.md @@ -0,0 +1,30 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Error Handling Distinguish + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services, including real-time device integration servers (e.g., android-device-mcp), tool-based integration components that expose capabilities to external clients, bidirectional communication boundaries requiring protocol standardization, and integration points that require capability negotiation and discovery. + +### Rules + +- **R-MCP-001** MUST: Error handling MUST distinguish between tool-level errors (logged with tool context) and fatal server errors (logged as fatal). + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization includes capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic uses collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers +- Error handling code distinguishes tool-level errors from fatal server errors with contextual logging prefixes + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk imports, code review checklist verification of capabilities declaration, and integration tests verifying tool discovery are mandatory. CI pipeline MUST fail if integration servers lack MCP SDK imports or capabilities declaration. Code review MUST block merge if tool lookup patterns bypass protocol-standard discovery mechanisms or if error handling does not distinguish between tool-level and fatal errors. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-log-entries-b607.md b/.actual/rules/cross-cutting-error-log-entries-b607.md new file mode 100644 index 00000000000..0a49dc477d2 --- /dev/null +++ b/.actual/rules/cross-cutting-error-log-entries-b607.md @@ -0,0 +1,29 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Error Log Entries + +These rules are ALWAYS ACTIVE for library modules in TypeScript (Node.js environments) and Kotlin (Retrofit-based HTTP clients) that implement error logging using platform-native error reporting mechanisms. + +### Rules + +- **R-20-001** MUST: Error log entries MUST include contextual information identifying the error source (tool name, operation type, or error category). + +### Verify + +```bash +# Check for console.error usage in TypeScript libraries +grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" + +# Check for Response.error usage in Kotlin libraries +grep -r "Response\.error" --include="*.kt" src/ | head -20 + +# Verify no external logging framework imports in library code +grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l +``` + +**Accept when:** +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + + +Claude Code MUST NOT skip or defer verification. Code review checklist and CI pipeline dependency analysis are mandatory before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-logging-occur-5985.md b/.actual/rules/cross-cutting-error-logging-occur-5985.md new file mode 100644 index 00000000000..b6e139ef3ed --- /dev/null +++ b/.actual/rules/cross-cutting-error-logging-occur-5985.md @@ -0,0 +1,29 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Error Logging Occur + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, tool execution error handling within the server capabilities boundary, fatal error conditions that terminate server operation, and stdio-based transport layer error reporting. + +### Rules + +- **R-LOGGING-001** MUST: Error logging MUST occur synchronously to ensure visibility before process termination in fatal scenarios. + +### Verify + +```bash +# Verify tool execution errors include console.error with tool name context +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal error handlers log to console.error +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify tool resolution pattern is present +grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + + +Claude Code MUST NOT skip or defer verification. All three grep commands must return results indicating proper console.error usage in error handling paths before accepting changes to MCP server error handling. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-messages-include-a9af.md b/.actual/rules/cross-cutting-error-messages-include-a9af.md new file mode 100644 index 00000000000..9e3b9e04bd7 --- /dev/null +++ b/.actual/rules/cross-cutting-error-messages-include-a9af.md @@ -0,0 +1,30 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Error Messages Include + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, tool execution error handling within the server capabilities boundary, fatal error conditions that terminate server operation, and stdio-based transport layer error reporting. + +### Rules + +- **R-CONSOLE-001** SHOULD: Error messages SHOULD include sufficient context to identify the failing component without requiring additional correlation. + +### Verify + +```bash +# Verify tool execution errors include console.error with tool name context +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal errors are logged to console.error before process termination +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify tool resolution using tools.find pattern is present +grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name +- Error messages use consistent prefixing (e.g., 'Tool error ({name}):' for tool-scoped errors and 'Fatal error:' for server-level errors) + + +Claude Code MUST NOT skip or defer verification. All three grep commands must execute successfully and return results matching the expected patterns before accepting changes to error handling paths in MCP server implementations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-response-body-f91a.md b/.actual/rules/cross-cutting-error-response-body-f91a.md new file mode 100644 index 00000000000..be71d073a7f --- /dev/null +++ b/.actual/rules/cross-cutting-error-response-body-f91a.md @@ -0,0 +1,29 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Error Response Body + +These rules are ALWAYS ACTIVE for all network layer unit tests in `network/src/test/kotlin/**/*Test.kt`, particularly tests validating `toBitwardenError()` extension functions, `parseErrorBodyOrNull()` error parsing logic, and HTTP error response mocking for status codes 400-599. + +### Rules + +- **R-ERR-001** MUST: Error response body parsing tests MUST use `assertEquals` to validate extracted `message` and `validationErrors` fields. + +### Verify + +```bash +# Count Response.error() usage in test files +grep -r "Response.error" network/src/test/kotlin/ | wc -l + +# Count @Test methods validating exception-to-error transformations +grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l + +# Count assertEquals/assertTrue assertions in error-related tests +grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l +``` + +**Accept when:** +- At least 2 test files use `Response.error()` with `toResponseBody()` for HTTP error mocking +- All custom exception types have corresponding `@Test` methods validating `toBitwardenError()` transformations +- Error parsing tests include `assertEquals` assertions for both `message` and `validationErrors` fields + + +Claude Code MUST NOT skip or defer verification of these rules. All new error response body parsing tests MUST include `assertEquals` assertions validating extracted fields. Pull requests adding new exception types without corresponding tests are blocked until tests are added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-response-json-c4e2.md b/.actual/rules/cross-cutting-error-response-json-c4e2.md new file mode 100644 index 00000000000..ec6a9412214 --- /dev/null +++ b/.actual/rules/cross-cutting-error-response-json-c4e2.md @@ -0,0 +1,29 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Error Response Json + +These rules are ALWAYS ACTIVE for all network layer unit tests in `network/src/test/kotlin/**/*Test.kt`, particularly tests validating `toBitwardenError()` extension functions, `parseErrorBodyOrNull()` error parsing logic, and HTTP error response mocking for status codes 400-599. + +### Rules + +- **R-ERR-001** SHOULD: Error response JSON in tests SHOULD include both `message` and `validationErrors` fields to validate complete parsing logic. + +### Verify + +```bash +# Count Response.error() usage patterns in test files +grep -r "Response.error" network/src/test/kotlin/ | wc -l + +# Count @Test methods validating BitwardenError or Exception transformations +grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l + +# Count assertEquals/assertTrue assertions in error-related test modules +grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l +``` + +**Accept when:** +- At least 2 test files use `Response.error()` with `toResponseBody()` for HTTP error mocking +- All custom exception types have corresponding `@Test` methods validating `toBitwardenError()` transformations +- Error parsing tests include `assertEquals` assertions for both `message` and `validationErrors` fields + + +Clause Code MUST NOT skip or defer verification. Pull requests adding new error types without corresponding tests validating both message and validationErrors fields are blocked until tests are added. Coverage drops in network error handling modules trigger build warnings. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-extension-functions-that-9c9d.md b/.actual/rules/cross-cutting-extension-functions-that-9c9d.md new file mode 100644 index 00000000000..d2985eea768 --- /dev/null +++ b/.actual/rules/cross-cutting-extension-functions-that-9c9d.md @@ -0,0 +1,35 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Extension Functions That + +These rules are ALWAYS ACTIVE for all custom kotlinx.serialization serializers, extension functions converting between domain models and SDK types, and JSON encoding/decoding at service and module boundaries. + +### Rules + +- **R-SER-001** SHOULD: Extension functions that convert domain models to SDK types (e.g., toSdkPolicyViews) SHOULD have tests verifying empty input and multi-item conversion. +- **R-SER-002** MUST: All custom serializers MUST have corresponding test classes with @Test methods validating JSON structure. +- **R-SER-003** MUST: Serialization tests MUST use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings. +- **R-SER-004** MUST: Tests for versioned schemas MUST validate type discriminator field values (e.g., 'v1', 'v2') in separate test methods per version. +- **R-SER-005** SHOULD: Mock factory functions (e.g., createMockPolicy) SHOULD be extracted to shared test utilities for reuse across test classes. + +### Verify + +```bash +# Count serializer test classes +grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l + +# Count buildJsonObject with assertEquals patterns +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l + +# Find serializer and extension test files using kotlinx.serialization +find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' +``` + +**Accept when:** +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases +- Mock factory functions are centralized in shared test utilities + + +Claude Code MUST NOT skip or defer verification of serialization test coverage and JSON structure validation. Pull requests adding serializers without tests MUST be blocked in code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-external-calls-add-5042.md b/.actual/rules/cross-cutting-external-calls-add-5042.md new file mode 100644 index 00000000000..4742d0be5cd --- /dev/null +++ b/.actual/rules/cross-cutting-external-calls-add-5042.md @@ -0,0 +1,35 @@ +# Standardize Set-Based Label Management for External Client Boundaries: External Calls Add + +These rules are ALWAYS ACTIVE for GitHub pull request labeling automation scripts and external client boundary interactions requiring label management based on configuration-driven pattern matching. + +### Rules + +- **R-EX-001** MUST: External API calls (gh_add_labels, gh_replace_labels) MUST be invoked only after all labels have been accumulated locally in a set-based structure. +- **R-EX-002** MUST: Initialize label sets early in the workflow to ensure all conditional branches can add labels safely. +- **R-EX-003** SHOULD: Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels. +- **R-EX-004** SHOULD: Validate JSON configuration schema on load to catch malformed patterns before runtime. +- **R-EX-005** SHOULD: Log the final label set before API calls to aid debugging and auditing. +- **R-EX-006** MAY: Implement unit tests that verify set operations produce expected deduplication behavior. + +### Verify + +```bash +# Detect set-based label accumulation patterns +grep -r '\.add("app:' .github/scripts/ | wc -l + +# Verify set initialization +grep -r 'labels.*=.*set()' .github/scripts/ | wc -l + +# Validate Python syntax +python3 -m py_compile .github/scripts/label-pr.py +``` + +**Accept when:** +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation +- JSON configuration parsing includes error handling (try-except blocks) + + +Claude Code MUST NOT skip or defer verification. All three verify commands must execute successfully before accepting changes to label management automation scripts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fatal-errors-logged-0e95.md b/.actual/rules/cross-cutting-fatal-errors-logged-0e95.md new file mode 100644 index 00000000000..a82ee146486 --- /dev/null +++ b/.actual/rules/cross-cutting-fatal-errors-logged-0e95.md @@ -0,0 +1,34 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Fatal Errors Logged + +These rules are ALWAYS ACTIVE for all Android device MCP server implementations using the Model Context Protocol SDK for stdio-based transport and tool registration. + +### Rules + +- **R-MCP-001** MUST: Fatal errors MUST be logged using console.error with 'Fatal error:' prefix + +### Verify + +```bash +# Verify SDK imports are present +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . + +# Verify stdio transport import +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify console.error logging for tool errors +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capabilities with tools support +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Fatal errors are logged with 'Fatal error:' prefix using console.error + + +Claude Code MUST NOT skip or defer verification of these rules. Static analysis scanning, code review verification, and automated testing are mandatory before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fatal-server-errors-5945.md b/.actual/rules/cross-cutting-fatal-server-errors-5945.md new file mode 100644 index 00000000000..b732860d2f9 --- /dev/null +++ b/.actual/rules/cross-cutting-fatal-server-errors-5945.md @@ -0,0 +1,35 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Fatal Server Errors + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, including tool execution error handling within MCP servers, fatal error reporting in server lifecycle, and stdio-based MCP server communication. + +### Rules + +- **R-MCP-001** MUST: Fatal server errors MUST be logged using console.error with the format 'Fatal error: {error}'. +- **R-MCP-002** MUST: Tool execution errors MUST be logged using console.error with the format 'Tool error ({toolName}): {error.message}'. +- **R-MCP-003** MUST: The server MUST use stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr). +- **R-MCP-004** MUST: Tool execution MUST be wrapped in try-catch blocks with appropriate error logging. +- **R-MCP-005** MUST: The server MUST import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities. + +### Verify + +```bash +# Verify tool error logging uses console.error with 'Tool error' prefix +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal errors are logged with console.error using 'Fatal error' prefix +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify server imports @modelcontextprotocol/sdk modules +grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts +``` + +**Accept when:** +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure +- Tool execution is wrapped in try-catch blocks +- stdio transport is configured from @modelcontextprotocol/sdk/server/stdio.js + + +Claude Code MUST NOT skip or defer verification. All rules must be verified before accepting implementation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fatal-server-level-bc5d.md b/.actual/rules/cross-cutting-fatal-server-level-bc5d.md new file mode 100644 index 00000000000..678d00c8320 --- /dev/null +++ b/.actual/rules/cross-cutting-fatal-server-level-bc5d.md @@ -0,0 +1,30 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Fatal Server Level + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, tool execution error handling within the server capabilities boundary, fatal error conditions that terminate server operation, and stdio-based transport layer error reporting. + +### Rules + +- **R-CONSOLE-001** MUST: Fatal server-level errors MUST be logged using console.error with the prefix 'Fatal error:' followed by the error object. + +### Verify + +```bash +# Verify fatal error logging is present +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify tool error logging with context +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify tool resolution pattern +grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All fatal error handlers log to console.error with 'Fatal error:' prefix before process termination +- All tool execution error paths include console.error calls with tool name context +- Tool resolution using tools.find pattern is followed by error handling with captured tool name +- Error log output format and content are validated by integration tests + + +Claude Code MUST NOT skip or defer verification. All three grep commands must return results confirming fatal error logging, tool error logging, and tool resolution patterns are present in the codebase. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-file-system-operations-39de.md b/.actual/rules/cross-cutting-file-system-operations-39de.md new file mode 100644 index 00000000000..2cab7a3f49e --- /dev/null +++ b/.actual/rules/cross-cutting-file-system-operations-39de.md @@ -0,0 +1,41 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: File System Operations + +These rules are ALWAYS ACTIVE for all TypeScript test specifications (*.spec.ts, *.test.ts), Python automation scripts in .github/scripts/, validation and parsing utilities, and CI/CD pipeline scripts. + +### Rules + +- **R-FSO-001** MUST: File system operations in Node.js test and automation scripts MUST use the node:fs and node:path core modules rather than third-party file system libraries. +- **R-FSO-002** MUST: Test specifications and automation scripts MUST import only standard library modules (json, sys, os, argparse in Python; node:fs, node:path in Node.js) for core functionality without external dependencies. +- **R-FSO-003** MUST: Data access patterns MUST consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts rather than third-party collection libraries. +- **R-FSO-004** SHOULD: Create shared utility modules for common patterns (parseJsonFile(), findInCollection(), addToSet()) to reduce duplication while maintaining standard library usage. +- **R-FSO-005** SHOULD: Document encoding assumptions (UTF-8) explicitly and add file size checks for large file handling in file I/O operations. + +### Verify + +```bash +# Verify vitest usage in TypeScript test specifications +grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l + +# Verify node:fs and node:path usage in TypeScript and JavaScript files +grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l + +# Verify standard library imports in Python automation scripts +grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l + +# Verify native collection method usage +grep -r "\.find(\|\.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +# Verify no prohibited third-party imports in test/automation directories +grep -r "import.*lodash\|import.*ramda\|from lodash\|from ramda" .claude/mcp/**/*.spec.ts .claude/mcp/**/*.test.ts .github/scripts/**/*.py && echo "FAIL: Prohibited imports found" || echo "PASS: No prohibited imports" +``` + +**Accept when:** +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts +- No prohibited third-party imports (lodash, ramda, etc.) are detected in test or automation script directories +- File I/O operations explicitly document encoding assumptions and include appropriate error handling + + +Claude Code MUST NOT skip or defer verification of these rules. CI pipeline static analysis MUST check for prohibited third-party imports in test and automation script directories. Code review MUST verify standard library usage for new test specifications and automation scripts. Pull requests adding external dependencies to automation scripts MUST require architecture review and explicit justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-functions-interacting-external-ad14.md b/.actual/rules/cross-cutting-functions-interacting-external-ad14.md new file mode 100644 index 00000000000..a6b10fb3db7 --- /dev/null +++ b/.actual/rules/cross-cutting-functions-interacting-external-ad14.md @@ -0,0 +1,34 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Functions Interacting External + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that implement GitHub integration automation, particularly those exposing public contract functions for configuration loading, GitHub data retrieval, and label manipulation. + +### Rules + +- **R-GH-001** MUST: Functions interacting with external GitHub APIs MUST use subprocess invocation of gh CLI rather than direct HTTP client libraries. +- **R-GH-002** MUST: All GitHub API interaction functions MUST be prefixed with 'gh_' to clearly mark the integration boundary and distinguish from internal helper functions. +- **R-GH-003** MUST: Configuration file parsing functions MUST use json.load() with explicit exception handling (try/except json.JSONDecodeError). +- **R-GH-004** MUST: Subprocess calls MUST capture both stdout and stderr, logging errors with context about which gh command failed. +- **R-GH-005** SHOULD: Label manipulation SHOULD use Python sets for deduplication, converting to lists only when calling gh CLI commands. + +### Verify + +```bash +# Verify GitHub integration functions follow naming convention +grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py + +# Verify JSON parsing includes explicit exception handling +grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py + +# Verify GitHub API interactions use subprocess invocation of gh CLI +grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py +``` + +**Accept when:** +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries +- Subprocess calls capture and log both stdout and stderr with contextual error information + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST pass before accepting changes to GitHub integration scripts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-github-integration-scripts-f2fa.md b/.actual/rules/cross-cutting-github-integration-scripts-f2fa.md new file mode 100644 index 00000000000..7020c764003 --- /dev/null +++ b/.actual/rules/cross-cutting-github-integration-scripts-f2fa.md @@ -0,0 +1,34 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Github Integration Scripts + +These rules are ALWAYS ACTIVE for all GitHub integration automation scripts in `.github/scripts/` that interact with GitHub APIs via subprocess invocation of the gh CLI. + +### Rules + +- **R-GH-001** MUST: GitHub integration scripts MUST expose public contract functions with explicit names following the pattern: `load_config_json`, `gh_get_*`, `gh_add_*`, `gh_replace_*` for configuration, retrieval, and mutation operations respectively. +- **R-GH-002** MUST: All configuration file parsing MUST include explicit exception handling for `json.JSONDecodeError` with clear error messages indicating which configuration file failed to parse. +- **R-GH-003** MUST: GitHub API interactions MUST use subprocess invocation of the `gh` CLI rather than direct HTTP client libraries or external API wrapper packages. +- **R-GH-004** MUST: Subprocess calls to `gh` commands MUST capture both stdout and stderr, with error logging that includes context about which gh command failed. +- **R-GH-005** SHOULD: Label manipulation operations SHOULD use Python sets for deduplication, converting to lists only when passing arguments to gh CLI commands. + +### Verify + +```bash +# Verify all GitHub integration functions follow naming convention +grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py + +# Verify JSON parsing includes explicit exception handling +grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py + +# Verify GitHub API interactions use subprocess invocation of gh CLI +grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py +``` + +**Accept when:** +- All GitHub integration functions follow naming convention (`load_config_json`, `gh_*`) and are discoverable via grep +- JSON parsing includes explicit exception handling for `JSONDecodeError` in configuration loading functions +- GitHub API interactions use subprocess invocation of `gh` CLI rather than direct HTTP client libraries +- Subprocess calls capture and log both stdout and stderr with contextual error information + + +Claude Code MUST NOT skip or defer verification of these rules. All GitHub integration scripts MUST be checked against R-GH-001 through R-GH-005 before approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-github-interactions-encapsulated-dcfc.md b/.actual/rules/cross-cutting-github-interactions-encapsulated-dcfc.md new file mode 100644 index 00000000000..02857890cf3 --- /dev/null +++ b/.actual/rules/cross-cutting-github-interactions-encapsulated-dcfc.md @@ -0,0 +1,35 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Github Interactions Encapsulated + +These rules are ALWAYS ACTIVE for PR automation scripts in the `.github/scripts/` directory, JSON configuration files defining title_patterns and path_patterns, GitHub API wrapper functions, label assignment logic for application and component classification, and CI/CD workflows that trigger PR labeling automation. + +### Rules + +- **R-GH-001** MUST: GitHub API interactions MUST be encapsulated in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) to isolate external client boundaries. +- **R-GH-002** MUST: PR automation scripts MUST load JSON configuration with exception handling for json.JSONDecodeError to handle malformed configuration gracefully. +- **R-GH-003** MUST: Label assignment logic MUST evaluate both title_patterns and path_patterns from configuration to determine label application. +- **R-GH-004** SHOULD: GitHub API wrapper functions SHOULD use subprocess or GitHub REST API client with retry logic and exponential backoff for rate limiting and authentication failures. +- **R-GH-005** SHOULD: Label collection SHOULD use Python sets to automatically deduplicate labels before applying to PR. +- **R-GH-006** SHOULD: Logging statements SHOULD be added at key decision points (pattern matches, label additions) to enable debugging and audit trail. + +### Verify + +```bash +# Verify JSON configuration loading in label-pr.py +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions are defined +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' +``` + +**Accept when:** +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment +- Python syntax validation passes without errors + + +Claude Code MUST NOT skip or defer verification of these rules. All GitHub API interactions in PR automation scripts MUST be encapsulated in dedicated functions, and JSON configuration MUST be loaded with proper exception handling. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-handler-functions-coordinate-0482.md b/.actual/rules/cross-cutting-handler-functions-coordinate-0482.md new file mode 100644 index 00000000000..775255fee39 --- /dev/null +++ b/.actual/rules/cross-cutting-handler-functions-coordinate-0482.md @@ -0,0 +1,29 @@ +# Adopt Async Handler Pattern for Tool Operations: Handler Functions Coordinate + +These rules are ALWAYS ACTIVE for all tool implementations in the android-device-server MCP service, specifically all handler functions that coordinate asynchronous operations including validation, adb process execution, and file system I/O. + +### Rules + +- **R-HANDLER-001** MUST: Handler functions MUST coordinate asynchronous operations including validation, adb process execution, and file system I/O using async/await patterns. + +### Verify + +```bash +# Count async handler function exports +grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count await statements for adb operations +grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count Zod validation schemas +grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + + +Clause Code MUST NOT skip or defer verification. All tool implementations must be reviewed for compliance with the async handler pattern before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-handler-functions-not-b9c3.md b/.actual/rules/cross-cutting-handler-functions-not-b9c3.md new file mode 100644 index 00000000000..a61ec372827 --- /dev/null +++ b/.actual/rules/cross-cutting-handler-functions-not-b9c3.md @@ -0,0 +1,29 @@ +# Adopt Async Handler Pattern for Tool Operations: Handler Functions Not + +These rules are ALWAYS ACTIVE for all tool implementations in the android-device-server MCP service, specifically all handler functions that serve as entry points for tool invocation and coordinate asynchronous I/O operations. + +### Rules + +- **R-ASYNC-001** MUST: Handler functions MUST NOT block the Node.js event loop with synchronous I/O operations. + +### Verify + +```bash +# Count async handler function exports +grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count await statements for adb operations +grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count Zod validation schemas +grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + + +Claude Code MUST NOT skip or defer verification. All tool handler functions must be inspected for blocking I/O operations, and violations must be flagged during code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-handler-functions-use-5910.md b/.actual/rules/cross-cutting-handler-functions-use-5910.md new file mode 100644 index 00000000000..3a93e72fa52 --- /dev/null +++ b/.actual/rules/cross-cutting-handler-functions-use-5910.md @@ -0,0 +1,36 @@ +# Adopt Async Handler Pattern for Tool Operations: Handler Functions Use + +These rules are ALWAYS ACTIVE for all tool implementations in the android-device-server MCP service, specifically all handler functions that coordinate asynchronous I/O operations with external processes and file systems. + +### Rules + +- **R-HANDLER-001** SHOULD: Handler functions SHOULD use descriptive names that reflect the tool operation (e.g., capture, tapAt, findElementWithObstruction). +- **R-HANDLER-002** MUST: All tool handler functions that perform I/O operations MUST be declared as async functions. +- **R-HANDLER-003** MUST: All adb process calls within handlers MUST be awaited to prevent event loop blocking. +- **R-HANDLER-004** MUST: All tool modules MUST define Zod validation schemas for input parameters at module level. +- **R-HANDLER-005** MUST: All async handlers MUST include try-catch blocks with meaningful error messages that include operation context. +- **R-HANDLER-006** SHOULD: Validation SHOULD occur before entering async handler logic to enable early input rejection. + +### Verify + +```bash +# Count async handler function exports +grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count await statements for adb operations +grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count Zod validation schema definitions +grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters +- All async handlers include try-catch blocks with contextual error messages +- Handler function names are descriptive and reflect their tool operation + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for tool handler implementations in the android-device-server project. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-handler-screen-components-27e5.md b/.actual/rules/cross-cutting-handler-screen-components-27e5.md new file mode 100644 index 00000000000..190c2524e97 --- /dev/null +++ b/.actual/rules/cross-cutting-handler-screen-components-27e5.md @@ -0,0 +1,35 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Handler Screen Components + +These rules are ALWAYS ACTIVE for all Android UI screen implementations in app/src/main/kotlin UI packages, authentication feature module UI components, and any function that directly or indirectly emits Compose UI elements. + +### Rules + +- **R-COMPOSE-001** SHOULD: Handler and screen components SHOULD separate UI composition logic from business logic using ViewModel integration patterns. +- **R-COMPOSE-002** MUST: All UI component files MUST import androidx.compose.runtime.Composable explicitly. +- **R-COMPOSE-003** MUST: All functions that emit Compose UI elements MUST be annotated with @Composable. +- **R-COMPOSE-004** SHOULD: Composable functions SHOULD use PascalCase naming convention to distinguish from regular functions. +- **R-COMPOSE-005** SHOULD: UI composition SHOULD use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives. +- **R-COMPOSE-006** SHOULD: State management SHOULD integrate androidx.compose.runtime.remember for state that should survive recomposition. + +### Verify + +```bash +# Count @Composable annotations in UI packages +grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Count explicit imports of Composable annotation +grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Find UI screen files missing @Composable annotation +find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation +- All UI component files contain explicit androidx.compose.runtime.Composable imports + + +Claude Code MUST NOT skip or defer verification. Build failure occurs if Composable functions violate compiler constraints. Code review rejection is required for UI functions missing @Composable annotation. Automated linting warnings flag missing androidx.compose.runtime.Composable imports. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-error-response-b6ac.md b/.actual/rules/cross-cutting-http-error-response-b6ac.md new file mode 100644 index 00000000000..dec4e116cbf --- /dev/null +++ b/.actual/rules/cross-cutting-http-error-response-b6ac.md @@ -0,0 +1,36 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Http Error Response + +These rules are ALWAYS ACTIVE for all network layer unit tests in `network/src/test/kotlin/**/*Test.kt` that validate HTTP error response handling, exception-to-error mappings, and error body parsing logic. + +### Rules + +- **R-HTTP-ERR-001** MUST: HTTP error response tests MUST use OkHttp's `Response.error()` with `ResponseBody.toResponseBody()` to create mock error responses. +- **R-HTTP-ERR-002** MUST: Tests validating `toBitwardenError()` extension functions MUST include assertions for both exception type mapping and resulting HTTP status codes. +- **R-HTTP-ERR-003** MUST: Tests validating `parseErrorBodyOrNull()` error parsing logic MUST include assertions for both `message` and `validationErrors` fields from structured JSON response bodies. +- **R-HTTP-ERR-004** SHOULD: Test methods SHOULD follow clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions. +- **R-HTTP-ERR-005** SHOULD: Multi-line JSON response bodies in tests SHOULD use `trimIndent()` to improve test readability and maintainability. +- **R-HTTP-ERR-006** SHOULD: Related error tests SHOULD be grouped in dedicated test classes (e.g., `BitwardenErrorTest` for exception mappings, `ExceptionExtensionsTest` for parsing logic). +- **R-HTTP-ERR-007** SHOULD: Test suites SHOULD include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON). + +### Verify + +```bash +# Count Response.error() usage in test files +grep -r "Response.error" network/src/test/kotlin/ | wc -l + +# Count @Test methods validating exception mappings +grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l + +# Count assertEquals/assertTrue assertions in error handling tests +grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l +``` + +**Accept when:** +- At least 2 test files use `Response.error()` with `toResponseBody()` for HTTP error mocking +- All custom exception types (CookieRedirectException, LocalNetworkAccessException) have corresponding `@Test` methods validating `toBitwardenError()` transformations +- Error parsing tests include `assertEquals` assertions for both `message` and `validationErrors` fields +- Test methods follow arrange-act-assert structure with clear separation of concerns + + +Claude Code MUST NOT skip or defer verification of these rules. All new error handling tests and exception type additions MUST comply with R-HTTP-ERR-001 through R-HTTP-ERR-007 before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-implementations-extend-console-470c.md b/.actual/rules/cross-cutting-implementations-extend-console-470c.md new file mode 100644 index 00000000000..69942a1e8ea --- /dev/null +++ b/.actual/rules/cross-cutting-implementations-extend-console-470c.md @@ -0,0 +1,30 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Implementations Extend Console + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, particularly tool execution error handling within the server capabilities boundary and fatal error conditions that terminate server operation. + +### Rules + +- **R-CONSOLE-001** MAY: Implementations MAY extend console.error logging with structured error objects for enhanced debugging. + +### Verify + +```bash +# Verify tool execution error paths include console.error with tool name context +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal error handlers log to console.error before process termination +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify tool resolution using tools.find pattern is followed by error handling +grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All tool execution error paths include console.error calls with tool name context (e.g., 'Tool error ({name}):') +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name +- Error messages include tool name or error category as structured prefixes for basic parsing + + +Claude Code MUST NOT skip or defer verification. All three grep commands must return results confirming console.error usage in error handling paths before accepting implementation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-implementations-extend-error-dbb8.md b/.actual/rules/cross-cutting-implementations-extend-error-dbb8.md new file mode 100644 index 00000000000..7023345990f --- /dev/null +++ b/.actual/rules/cross-cutting-implementations-extend-error-dbb8.md @@ -0,0 +1,34 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Implementations Extend Error + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, particularly tool execution error handling and fatal error reporting in stdio-based MCP server communication. + +### Rules + +- **R-MCP-001** MUST: Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities. +- **R-MCP-002** MUST: Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}'. +- **R-MCP-003** MUST: Implement top-level error handlers for fatal errors using console.error('Fatal error:', error). +- **R-MCP-004** MUST: Use stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr). +- **R-MCP-005** MAY: Implementations MAY extend error logging with additional context fields beyond name and message. + +### Verify + +```bash +# Verify tool error logging uses console.error with 'Tool error ({name}):' prefix +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal errors are logged with console.error using 'Fatal error:' prefix +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify server imports @modelcontextprotocol/sdk modules for server infrastructure +grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts +``` + +**Accept when:** +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure +- Stdio transport is configured to separate protocol messages (stdout) from errors (stderr) + + +Claude Code MUST NOT skip or defer verification. All grep-based verification commands MUST pass before accepting implementation. Code review MUST check for console.error usage patterns. Runtime testing of error scenarios MUST verify stderr output. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-input-validation-occur-478e.md b/.actual/rules/cross-cutting-input-validation-occur-478e.md new file mode 100644 index 00000000000..ee238a59417 --- /dev/null +++ b/.actual/rules/cross-cutting-input-validation-occur-478e.md @@ -0,0 +1,31 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Input Validation Occur + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-VALIDATION-001** MUST: Input validation MUST occur at the API boundary before the input reaches core business logic or is passed to downstream services. + +### Verify + +```bash +# Check for schema validation usage in TypeScript tool handlers +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Check for JSON parsing in Python scripts +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation-specific tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions +- For TypeScript tools, validation schemas are defined using zod's z.object() with explicit types +- For Python scripts, json.load() is used with subsequent schema validation or a Python schema validation library (pydantic, marshmallow) + + +Claude Code MUST NOT skip or defer verification. All public API endpoints must demonstrate schema-based input validation at the boundary before processing external input. Code review and CI/CD pipeline tests must verify validation behavior for each endpoint. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-input-validation-zod-39c6.md b/.actual/rules/cross-cutting-input-validation-zod-39c6.md new file mode 100644 index 00000000000..91186a6e355 --- /dev/null +++ b/.actual/rules/cross-cutting-input-validation-zod-39c6.md @@ -0,0 +1,36 @@ +# Adopt Async Handler Pattern for Tool Operations: Input Validation Zod + +These rules are ALWAYS ACTIVE for all tool implementations in the android-device-server MCP service, specifically all handler functions that coordinate asynchronous operations including adb process execution, file system I/O, and input validation. + +### Rules + +- **R-ASYNC-001** MUST: Input validation using Zod schemas MUST occur before handler execution begins. +- **R-ASYNC-002** MUST: All tool handler functions that perform I/O operations MUST be declared as async functions. +- **R-ASYNC-003** MUST: All adb operations and file system operations within handlers MUST be awaited to prevent event loop blocking. +- **R-ASYNC-004** MUST: All async handlers MUST include try-catch blocks with meaningful error messages that include operation context. +- **R-ASYNC-005** SHOULD: Zod validation schemas SHOULD be defined at module level and reused across handler invocations. +- **R-ASYNC-006** SHOULD: Long-running adb operations SHOULD implement timeouts to prevent indefinite promise accumulation. + +### Verify + +```bash +# Count async handler exports in tool implementations +grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Verify adb operations are awaited +grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Verify Zod validation schemas are defined +grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters +- All async handlers include try-catch blocks with contextual error messages +- Input validation occurs before handler logic execution begins + + +Claude Code MUST NOT skip or defer verification of these rules. All tool implementations MUST be reviewed against R-ASYNC-001 through R-ASYNC-006 before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-components-separate-dbfa.md b/.actual/rules/cross-cutting-integration-components-separate-dbfa.md new file mode 100644 index 00000000000..fb91218b30a --- /dev/null +++ b/.actual/rules/cross-cutting-integration-components-separate-dbfa.md @@ -0,0 +1,29 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Integration Components Separate + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services. + +### Rules + +- **R-MCP-001** MAY: Integration components MAY separate validation logic (./utils/validation.js) and tool implementations (./tools/capture.js) into dedicated modules. + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization includes capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic uses collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files is mandatory. Code review checklist requiring capabilities declaration in server initialization is mandatory. Integration tests verifying tool discovery and invocation through MCP protocol are mandatory. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-servers-use-a61c.md b/.actual/rules/cross-cutting-integration-servers-use-a61c.md new file mode 100644 index 00000000000..f5fc78f726e --- /dev/null +++ b/.actual/rules/cross-cutting-integration-servers-use-a61c.md @@ -0,0 +1,29 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Integration Servers Use + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services, including real-time device integration servers, tool-based integration components, bidirectional communication boundaries, and integration points requiring capability negotiation and discovery. + +### Rules + +- **R-MCP-001** SHOULD: Integration servers SHOULD use stdio transport (@modelcontextprotocol/sdk/server/stdio.js) for process-based communication boundaries. + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization with capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic using collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files is mandatory. Code review checklist requiring capabilities declaration in server initialization is mandatory. Integration tests verifying tool discovery and invocation through MCP protocol are mandatory. CI pipeline MUST fail if integration servers lack MCP SDK imports or capabilities declaration. Code review MUST block merge if tool lookup patterns bypass protocol-standard discovery mechanisms. Architecture review is required for any custom protocol implementation in real-time integration boundaries. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-test-scripts-537e.md b/.actual/rules/cross-cutting-integration-test-scripts-537e.md new file mode 100644 index 00000000000..9e85ab8fbd4 --- /dev/null +++ b/.actual/rules/cross-cutting-integration-test-scripts-537e.md @@ -0,0 +1,34 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Integration Test Scripts + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON responses from external APIs (JIRA, GitHub, and similar services), as well as integration test utilities that process configuration files with optional fields. + +### Rules + +- **R-INT-001** MUST: Integration test scripts MUST use the `.get()` method when accessing dictionary keys from external API responses. +- **R-INT-002** MUST: When accessing nested fields, use `.get()` with empty dict default for intermediate keys: `response.get('fields', {}).get('field_name')`. +- **R-INT-003** SHOULD: Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling. +- **R-INT-004** SHOULD: Add comments documenting why a field might be missing when using `.get()` for non-obvious cases. +- **R-INT-005** MAY: Consider logging at debug level when `.get()` returns a default value to aid troubleshooting. + +### Verify + +```bash +# Count .get() usage in integration scripts +grep -r '\.get(' .github/scripts/*.py | wc -l + +# Count direct bracket notation (potential violations) +grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l + +# Verify scripts compile without syntax errors +python -m py_compile .github/scripts/*.py +``` + +**Accept when:** +- Integration scripts in `.github/scripts/` use `.get()` for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields +- No KeyError exceptions are raised during CI/CD workflow execution + + +Clause Code MUST NOT skip or defer verification. All integration scripts must be reviewed for compliance with R-INT-001 through R-INT-005 before merge. Violations trigger code review feedback requesting `.get()` usage for external API access. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-intent-processing-logic-1ad0.md b/.actual/rules/cross-cutting-intent-processing-logic-1ad0.md new file mode 100644 index 00000000000..7b1ee0160c0 --- /dev/null +++ b/.actual/rules/cross-cutting-intent-processing-logic-1ad0.md @@ -0,0 +1,35 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Intent Processing Logic + +These rules are ALWAYS ACTIVE for all Android ViewModels serving as public API boundaries for system integrations, including credential provider APIs, authentication callback handlers, and autofill service interactions. + +### Rules + +- **R-HILT-001** MUST: All ViewModels handling Intent-based public API interactions MUST be annotated with `@HiltViewModel`. +- **R-HILT-002** MUST: All public API boundary ViewModels MUST inject dependencies through constructor parameters annotated with `@Inject`. +- **R-HILT-003** SHOULD: Intent processing logic SHOULD be coordinated through injected repository or manager components rather than directly in ViewModel. +- **R-HILT-004** SHOULD: Each public API ViewModel SHOULD define sealed action types for type-safe contract enforcement between system APIs and application logic. +- **R-HILT-005** SHOULD: All public API ViewModels SHOULD extend BaseViewModel and use sealed action types (e.g., CredentialProviderAction, AuthCallbackAction) for Intent processing. +- **R-HILT-006** MAY: Legacy ViewModels predating Hilt adoption MAY be exempted from this standard with documented exception (EXC-001) and approved migration timeline. + +### Verify + +```bash +# Verify @HiltViewModel annotation on public API boundary ViewModels +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l + +# Verify sealed action types are defined +grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l + +# Verify public API ViewModels extend BaseViewModel and use @HiltViewModel +find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l +``` + +**Accept when:** +- All ViewModels handling Intent-based public API interactions contain `@HiltViewModel` annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters +- Intent processing logic is delegated to injected repository or manager components, not embedded directly in ViewModel + + +Clause Code MUST NOT skip or defer verification. All public API boundary ViewModels must pass the verify commands before acceptance. Violations block CI pipeline and require architecture team review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-internal-functions-implement-3f09.md b/.actual/rules/cross-cutting-internal-functions-implement-3f09.md new file mode 100644 index 00000000000..f4868da76af --- /dev/null +++ b/.actual/rules/cross-cutting-internal-functions-implement-3f09.md @@ -0,0 +1,33 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Internal Functions Implement + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON configuration, accept command-line arguments, or interact with external APIs and systems. + +### Rules + +- **R-IVIP-001** MUST: Wrap all `json.load()` calls in try-except blocks with specific exception handling for `JSONDecodeError` to provide clear error messages. +- **R-IVIP-002** MUST: Replace direct dictionary key access (e.g., `config['key']`) with safe access patterns (e.g., `config.get('key', default_value)`) or explicit `'key' in dict` checks throughout internal scripts. +- **R-IVIP-003** MUST: Use `argparse.ArgumentParser` for all command-line argument parsing with explicit type specifications and help text. +- **R-IVIP-004** MAY: Internal API functions MAY implement additional schema validation using JSON Schema or similar validation frameworks for complex configuration structures. + +### Verify + +```bash +# Check for json.load() calls without try-except blocks +grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' + +# Check for unsafe dictionary access patterns (direct bracket notation without .get()) +grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 + +# Verify argparse usage in scripts accepting arguments +find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l +``` + +**Accept when:** +- All Python scripts that use `json.load()` include try-except blocks with `JSONDecodeError` or general exception handling +- Dictionary access in configuration parsing uses `.get()` methods or explicit `'key' in dict` checks rather than direct bracket notation +- Scripts accepting command-line arguments use `argparse` or equivalent structured parsing libraries +- Configuration schema is documented in script docstrings or adjacent README files + + +Claude Code MUST NOT skip or defer verification. All three verification commands MUST pass before accepting changes to internal API scripts. Code review checklist MUST include input validation verification. Static analysis tools (pylint, bandit) MUST be configured to flag unsafe dictionary access and missing exception handling. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-internal-scripts-that-a6ed.md b/.actual/rules/cross-cutting-internal-scripts-that-a6ed.md new file mode 100644 index 00000000000..d41a5e6fea3 --- /dev/null +++ b/.actual/rules/cross-cutting-internal-scripts-that-a6ed.md @@ -0,0 +1,37 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Internal Scripts That + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON configuration files, accept command-line arguments, or interact with external APIs and systems. + +### Rules + +- **R-IAPI-001** MUST: Internal API scripts that parse JSON configuration files MUST use exception handling (try-except blocks) to catch json parsing errors and handle malformed input gracefully. +- **R-IAPI-002** MUST: Dictionary access in configuration parsing MUST use `.get()` methods or explicit `'key in dict'` checks rather than direct bracket notation to prevent KeyError exceptions. +- **R-IAPI-003** MUST: Scripts accepting command-line arguments MUST use `argparse` or equivalent structured parsing libraries instead of direct `sys.argv` parsing. + +### Verify + +```bash +# Check for json.load() calls without try-except blocks +grep -r 'json\.load' .github/scripts/ | while read line; do + file=$(echo "$line" | cut -d: -f1) + if ! grep -q "try:" "$file"; then + echo "Missing exception handling: $file" + fi +done + +# Check for unsafe dictionary access patterns (direct bracket notation) +grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' || echo "No unsafe dictionary access detected" + +# Verify argparse usage in scripts with command-line arguments +find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l +``` + +**Accept when:** +- All Python scripts that use `json.load()` include try-except blocks with `JSONDecodeError` or general exception handling +- Dictionary access in configuration parsing uses `.get()` methods or explicit `'key in dict'` checks rather than direct bracket notation +- Scripts accepting command-line arguments use `argparse` or equivalent structured parsing libraries +- Configuration schema is documented in script docstrings or adjacent README files + + +Claude Code MUST NOT skip or defer verification of these rules. All three rule levels (R-IAPI-001, R-IAPI-002, R-IAPI-003) are mandatory for scripts in scope. Code review and static analysis verification is required before approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-internal-that-process-c6b2.md b/.actual/rules/cross-cutting-internal-that-process-c6b2.md new file mode 100644 index 00000000000..a42f934b40e --- /dev/null +++ b/.actual/rules/cross-cutting-internal-that-process-c6b2.md @@ -0,0 +1,40 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Internal That Process + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON configuration, process command-line arguments, or interact with external APIs (GitHub, CI/CD systems). + +### Rules + +- **R-IVCP-001** MUST: All Python scripts that use `json.load()` include try-except blocks with specific exception handling for `JSONDecodeError` or general exceptions to provide clear error messages. +- **R-IVCP-002** MUST: Dictionary access in configuration parsing uses `.get()` methods or explicit `'key' in dict` checks rather than direct bracket notation (`dict['key']`). +- **R-IVCP-003** MUST: Scripts accepting command-line arguments use `argparse` or equivalent structured parsing libraries with explicit type specifications and help text. +- **R-IVCP-004** SHOULD: Internal APIs that process pattern matching (title_patterns, path_patterns) SHOULD validate pattern syntax before applying them to untrusted input. +- **R-IVCP-005** SHOULD: Configuration schema be documented in script docstrings or adjacent README files to guide validation implementation. + +### Verify + +```bash +# Check for json.load() calls without try-except blocks +grep -r 'json\.load' .github/scripts/ | while read line; do + file=$(echo "$line" | cut -d: -f1) + if ! grep -q "try:" "$file"; then + echo "Missing exception handling: $file" + fi +done + +# Check for unsafe dictionary access (direct bracket notation without .get()) +grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 + +# Verify argparse usage in scripts with command-line arguments +find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l +``` + +**Accept when:** +- All Python scripts that use `json.load()` include try-except blocks with `JSONDecodeError` or general exception handling +- Dictionary access in configuration parsing uses `.get()` methods or explicit `'key in dict'` checks rather than direct bracket notation +- Scripts accepting command-line arguments use `argparse` or equivalent structured parsing libraries +- Pattern matching validation is implemented before applying patterns to untrusted input +- Configuration schemas are documented alongside validation code + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for code review approval. Static analysis tools (pylint, bandit) MUST be configured to flag unsafe dictionary access and missing exception handling. Security review is required for scripts that interact with external systems or process untrusted input. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-json-configuration-files-8d59.md b/.actual/rules/cross-cutting-json-configuration-files-8d59.md new file mode 100644 index 00000000000..1d298a4145c --- /dev/null +++ b/.actual/rules/cross-cutting-json-configuration-files-8d59.md @@ -0,0 +1,41 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Json Configuration Files + +These rules are ALWAYS ACTIVE for all JSON configuration file processing, XML parsing operations, tool handlers in android-device-server, and GitHub automation scripts that accept external inputs. + +### Rules + +- **R-JSON-001** MUST: JSON configuration files MUST be validated using json.load() with exception handling to catch malformed data before processing. +- **R-JSON-002** MUST: All tool handlers in android-device-server (capture.ts, tap-at.ts) MUST define zod schemas with explicit type constraints for all required and optional parameters before processing inputs. +- **R-JSON-003** MUST: XML parsing operations MUST use fast-xml-parser with error handling configured for attribute handling and text node parsing based on UI hierarchy requirements. +- **R-JSON-004** MUST: GitHub automation scripts processing PR metadata and JSON configs MUST wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions. +- **R-JSON-005** MUST: All public API contracts exposed through ToolDefinition interfaces MUST include input validation at API boundaries using the validateInput utility from utils/validation.ts. +- **R-JSON-006** SHOULD: Schema validation errors SHOULD be sanitized to map validation errors to generic user-facing messages while logging detailed errors internally to prevent information disclosure vulnerabilities. +- **R-JSON-007** SHOULD: Complex nested schemas with recursive validation SHOULD be profiled on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases. + +### Verify + +```bash +# Count zod schema definitions in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count fast-xml-parser usage in parsers +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Count json.load() calls in GitHub scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation tests +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML +- No unvalidated external inputs are detected in TypeScript modules by static analysis +- Validation error responses are tested for all public APIs with invalid input scenarios + + +Clause Code MUST NOT skip or defer verification. All rules in this file are mandatory for code review approval. Pull requests introducing new API endpoints without input validation schemas MUST be blocked. Quarterly security audits MUST identify unvalidated input paths and create remediation tickets. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-json-data-loading-4759.md b/.actual/rules/cross-cutting-json-data-loading-4759.md new file mode 100644 index 00000000000..ccc7f95bf00 --- /dev/null +++ b/.actual/rules/cross-cutting-json-data-loading-4759.md @@ -0,0 +1,33 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Json Data Loading + +These rules are ALWAYS ACTIVE for test specification files (*.spec.ts, *.test.ts), automation scripts in .github/scripts/, validation and parsing utilities, and CI/CD pipeline scripts. + +### Rules + +- **R-JSON-001** SHOULD: JSON data loading SHOULD use `json.load(f)` in Python and `JSON.parse()` in TypeScript/JavaScript with explicit file handle management. + +### Verify + +```bash +# Verify vitest usage in TypeScript test specifications +grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l + +# Verify standard library file operations +grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l + +# Verify Python standard library imports only +grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l + +# Verify native collection method usage +grep -r "\.find(\|\.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l +``` + +**Accept when:** +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts +- No prohibited third-party imports (lodash, ramda, Pydantic, JSON Schema validators) are detected in test and automation script directories + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis MUST check for prohibited third-party imports in test and automation script directories. Code review MUST verify standard library usage for new test specifications and automation scripts. Pull requests adding external dependencies to automation scripts MUST require architecture review and explicit justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-json-object-construction-6557.md b/.actual/rules/cross-cutting-json-object-construction-6557.md new file mode 100644 index 00000000000..cc958fcbaab --- /dev/null +++ b/.actual/rules/cross-cutting-json-object-construction-6557.md @@ -0,0 +1,30 @@ +# Use JSON Builder DSL for Test Assertion Construction: Json Object Construction + +These rules are ALWAYS ACTIVE for all test files using kotlinx.serialization for JSON encoding/decoding verification. + +### Rules + +- **R-JSON-001** MUST: JSON object construction in tests MUST use the `put` function to add key-value pairs within `buildJsonObject` blocks. + +### Verify + +```bash +# Count buildJsonObject usage in test files +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l + +# Verify imports are present +grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' + +# Run serialization and extensions tests +./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' +``` + +**Accept when:** +- All serialization test files use `buildJsonObject` DSL for expected JSON construction +- No raw JSON strings are used in `assertEquals` calls for serialization verification +- Test suite passes with `buildJsonObject` assertions matching `json.encodeToJsonElement` output +- Type discriminator fields are verified first in `buildJsonObject` blocks for versioned state objects + + +Claude Code MUST NOT skip or defer verification of R-JSON-001. All test assertions for JSON serialization MUST use the buildJsonObject DSL pattern with put operations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-kotlin-network-libraries-a59d.md b/.actual/rules/cross-cutting-kotlin-network-libraries-a59d.md new file mode 100644 index 00000000000..ee0e727c363 --- /dev/null +++ b/.actual/rules/cross-cutting-kotlin-network-libraries-a59d.md @@ -0,0 +1,33 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Kotlin Network Libraries + +These rules are ALWAYS ACTIVE for library modules in TypeScript (Node.js environments) and Kotlin (Retrofit-based network layers) designed for reuse across multiple applications or services. + +### Rules + +- **R-20-001** SHOULD: Kotlin network libraries SHOULD use Response.error with appropriate HTTP status codes and JSON-formatted error messages for API-layer error responses. +- **R-20-002** SHOULD: TypeScript libraries SHOULD use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:'). +- **R-20-003** MUST: Library error messages MUST include sufficient context to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes. +- **R-20-004** MUST: Library modules MUST NOT introduce external logging framework dependencies (winston, pino, log4j, slf4j) for error logging. + +### Verify + +```bash +# Check for console.error usage in TypeScript libraries +grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" + +# Check for Response.error usage in Kotlin libraries +grep -r "Response\.error" --include="*.kt" src/ | head -20 + +# Verify no external logging framework imports in library code +grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l +``` + +**Accept when:** +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements +- Error messages include actionable context such as operation name, input parameters, or error codes + + +Clause Code MUST NOT skip or defer verification. Dependency analysis in CI pipeline MUST flag external logging framework dependencies in library modules. Code review MUST verify use of platform-native error logging mechanisms and presence of contextual information in error messages. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-label-accumulation-use-6360.md b/.actual/rules/cross-cutting-label-accumulation-use-6360.md new file mode 100644 index 00000000000..78171a99654 --- /dev/null +++ b/.actual/rules/cross-cutting-label-accumulation-use-6360.md @@ -0,0 +1,29 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Label Accumulation Use + +These rules are ALWAYS ACTIVE for GitHub pull request labeling automation scripts and external client boundary interactions requiring label management based on configuration-driven pattern matching. + +### Rules + +- **R-LABEL-001** MUST: Label accumulation MUST use set-based data structures to ensure automatic deduplication. + +### Verify + +```bash +# Detect set-based label accumulation patterns in automation scripts +grep -r '\.add("app:' .github/scripts/ | wc -l + +# Verify set initialization for label accumulation +grep -r 'labels.*=.*set()' .github/scripts/ | wc -l + +# Validate Python syntax in label automation scripts +python3 -m py_compile .github/scripts/label-pr.py +``` + +**Accept when:** +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + + +Claude Code MUST NOT skip or defer verification. All three verify commands must pass before accepting label accumulation logic. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-label-assignment-logic-e610.md b/.actual/rules/cross-cutting-label-assignment-logic-e610.md new file mode 100644 index 00000000000..cb66f6bc04c --- /dev/null +++ b/.actual/rules/cross-cutting-label-assignment-logic-e610.md @@ -0,0 +1,39 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Label Assignment Logic + +These rules are ALWAYS ACTIVE for PR automation scripts in `.github/scripts/` directory, JSON configuration files defining title_patterns and path_patterns, GitHub API wrapper functions, and CI/CD workflows that trigger PR labeling automation. + +### Rules + +- **R-LABEL-001** MUST: Label assignment logic MUST evaluate both title_patterns and path_patterns from configuration to determine applicable labels. +- **R-LABEL-002** MUST: All GitHub API interactions MUST be encapsulated in dedicated functions with `gh_` prefix. +- **R-LABEL-003** MUST: JSON configuration loading MUST include exception handling for `json.JSONDecodeError` to handle malformed configuration gracefully. +- **R-LABEL-004** SHOULD: Use Python sets for label collection to automatically deduplicate labels before applying to PR. +- **R-LABEL-005** SHOULD: Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail. +- **R-LABEL-006** SHOULD: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details. + +### Verify + +```bash +# Verify JSON configuration loading with exception handling +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions exist +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +# Verify both title_patterns and path_patterns are evaluated +grep -E '(title_patterns|path_patterns)' .github/scripts/label-pr.py | wc -l +``` + +**Accept when:** +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with `gh_` prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment +- JSON schema validation tests exist for configuration files +- Logging statements are present at pattern match and label assignment decision points + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for PR automation label assignment logic. Violations must be caught during code review and CI pipeline validation before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-label-manipulation-functions-1022.md b/.actual/rules/cross-cutting-label-manipulation-functions-1022.md new file mode 100644 index 00000000000..e70b0039855 --- /dev/null +++ b/.actual/rules/cross-cutting-label-manipulation-functions-1022.md @@ -0,0 +1,35 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Label Manipulation Functions + +These rules are ALWAYS ACTIVE for all GitHub automation scripts in `.github/scripts/` that implement label manipulation and GitHub API integration logic. + +### Rules + +- **R-LABEL-001** SHOULD: Label manipulation functions SHOULD use set-based data structures for deduplication and membership testing. +- **R-LABEL-002** MUST: All GitHub API interaction functions MUST be prefixed with 'gh_' to clearly mark the integration boundary and distinguish from internal helper functions. +- **R-LABEL-003** MUST: Configuration file parsing MUST include explicit exception handling for `json.JSONDecodeError` in all `load_config_json` and related configuration loading functions. +- **R-LABEL-004** MUST: GitHub API interactions MUST use subprocess invocation of gh CLI rather than direct HTTP client libraries. +- **R-LABEL-005** MUST: Subprocess calls MUST capture both stdout and stderr, logging errors with context about which gh command failed. + +### Verify + +```bash +# Verify GitHub integration function naming conventions +grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py + +# Verify JSON parsing includes explicit exception handling +grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py + +# Verify subprocess invocation of gh CLI +grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py +``` + +**Accept when:** +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries +- Label manipulation logic uses set-based operations (.add(), membership testing) for deduplication +- Subprocess calls include error handling that captures and logs both stdout and stderr + + +Claude Code MUST NOT skip or defer verification of these rules. All GitHub automation scripts in `.github/scripts/` MUST comply with the naming conventions, exception handling patterns, and subprocess invocation requirements before approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-label-operations-handle-1a7c.md b/.actual/rules/cross-cutting-label-operations-handle-1a7c.md new file mode 100644 index 00000000000..6ad1b88b808 --- /dev/null +++ b/.actual/rules/cross-cutting-label-operations-handle-1a7c.md @@ -0,0 +1,30 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Label Operations Handle + +These rules are ALWAYS ACTIVE for GitHub pull request labeling automation scripts and external client boundary interactions requiring label management based on configuration-driven pattern matching. + +### Rules + +- **R-LABEL-001** SHOULD: Label operations SHOULD handle JSON parsing exceptions gracefully to prevent automation failures. + +### Verify + +```bash +# Detect set-based label accumulation patterns +grep -r '\.add("app:' .github/scripts/ | wc -l + +# Verify set initialization in automation scripts +grep -r 'labels.*=.*set()' .github/scripts/ | wc -l + +# Validate Python syntax of label automation scripts +python3 -m py_compile .github/scripts/label-pr.py +``` + +**Accept when:** +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation +- JSON parsing is wrapped in try-except blocks to handle malformed configuration gracefully + + +Claude Code MUST NOT skip or defer verification of set-based label accumulation patterns and JSON exception handling in GitHub automation scripts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-label-operations-use-2e0e.md b/.actual/rules/cross-cutting-label-operations-use-2e0e.md new file mode 100644 index 00000000000..a8bdd1ced81 --- /dev/null +++ b/.actual/rules/cross-cutting-label-operations-use-2e0e.md @@ -0,0 +1,34 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Label Operations Use + +These rules are ALWAYS ACTIVE for PR automation scripts in `.github/scripts/` directory, JSON configuration files defining title_patterns and path_patterns, GitHub API wrapper functions, and label assignment logic for application and component classification. + +### Rules + +- **R-LABEL-001** SHOULD: Label operations SHOULD use set-based collection (.add, .remove) to ensure uniqueness and prevent duplicate label application. + +### Verify + +```bash +# Verify JSON configuration loading with exception handling +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions are encapsulated with gh_ prefix +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +# Verify set-based label collection usage +grep -E '(labels\.add|labels\.remove|set\(|\{.*\})' .github/scripts/label-pr.py +``` + +**Accept when:** +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment +- Label collection uses set-based operations (.add, .remove) to prevent duplicates +- JSON schema validation tests exist for configuration files + + +Claude Code MUST NOT skip or defer verification. All verify commands MUST execute successfully before accepting changes to PR automation label operations. Configuration validation errors MUST block PR automation workflow execution. Violation handling requires manual label review and explicit error logging for all GitHub API interactions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-libraries-provide-hooks-8771.md b/.actual/rules/cross-cutting-libraries-provide-hooks-8771.md new file mode 100644 index 00000000000..c901c32615d --- /dev/null +++ b/.actual/rules/cross-cutting-libraries-provide-hooks-8771.md @@ -0,0 +1,30 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Libraries Provide Hooks + +These rules are ALWAYS ACTIVE for library modules in TypeScript (Node.js environments) and Kotlin (Retrofit-based HTTP clients) that serve as integration points across multiple applications or services. + +### Rules + +- **R-20-005** MAY: Libraries MAY provide hooks or callbacks for consumers to integrate custom logging implementations while maintaining default platform-native error logging. + +### Verify + +```bash +# Check for console.error usage in TypeScript libraries +grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" + +# Check for Response.error usage in Kotlin libraries +grep -r "Response\.error" --include="*.kt" src/ | head -20 + +# Verify no external logging framework imports in library code +grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l +``` + +**Accept when:** +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements +- Error messages include actionable context such as operation identifiers, input validation failures, exception types, and error codes + + +Code review MUST verify use of platform-native error logging mechanisms. Dependency analysis in CI pipeline MUST flag external logging framework dependencies in library modules. Violations require code review feedback requesting removal of external logging dependencies and migration to platform-native mechanisms. Architecture review is required for libraries that cannot use platform-native error logging due to runtime constraints. Approved exceptions MUST be documented in library README with justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-library-error-logging-722f.md b/.actual/rules/cross-cutting-library-error-logging-722f.md new file mode 100644 index 00000000000..cd4d73fd8bc --- /dev/null +++ b/.actual/rules/cross-cutting-library-error-logging-722f.md @@ -0,0 +1,31 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Library Error Logging + +These rules are ALWAYS ACTIVE for library modules in TypeScript (Node.js environments) and Kotlin (Retrofit-based HTTP clients) that serve as integration points and are designed for reuse across multiple applications or services. + +### Rules + +- **R-LIB-ERR-001** MUST_NOT: Library error logging MUST NOT depend on application-specific logging frameworks or configurations that would create tight coupling between library and consumer. + +### Verify + +```bash +# Check for console.error usage in TypeScript libraries +grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" + +# Check for Response.error usage in Kotlin libraries +grep -r "Response\.error" --include="*.kt" src/ | head -20 + +# Verify no external logging framework imports in library code +grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l +``` + +**Accept when:** +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements +- For TypeScript libraries: error messages use descriptive prefixes identifying library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin libraries: Response.error uses appropriate HTTP status codes and JSON-formatted error messages + + +Clause R-LIB-ERR-001 verification is mandatory. Code review MUST check for platform-native error logging mechanisms. CI pipeline MUST flag external logging framework dependencies in library modules. Violations require removal of external logging dependencies and migration to platform-native mechanisms. Exceptions require technical lead or architecture review approval and documentation in library README. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-library-modules-use-2f7e.md b/.actual/rules/cross-cutting-library-modules-use-2f7e.md new file mode 100644 index 00000000000..ea76cfe4a6c --- /dev/null +++ b/.actual/rules/cross-cutting-library-modules-use-2f7e.md @@ -0,0 +1,30 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Library Modules Use + +These rules are ALWAYS ACTIVE for library modules in TypeScript (Node.js environments) and Kotlin (Retrofit-based HTTP clients) that serve as integration points or are designed for reuse across multiple applications or services. + +### Rules + +- **R-20-001** MUST: Library modules MUST use platform-native error logging mechanisms (console.error for TypeScript/Node.js, Response.error for Kotlin/Retrofit) rather than introducing external logging framework dependencies. + +### Verify + +```bash +# Check for console.error usage in TypeScript library code +grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" + +# Check for Response.error usage in Kotlin library code +grep -r "Response\.error" --include="*.kt" src/ | head -20 + +# Verify no external logging framework imports in library modules +grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l +``` + +**Accept when:** +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements +- Error messages include actionable context such as operation identifiers, input validation failures, exception types, and error codes + + +Claude Code MUST NOT skip or defer verification. Code review checklist and CI pipeline dependency analysis are mandatory before accepting library code changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-mcp-server-implementations-42f6.md b/.actual/rules/cross-cutting-mcp-server-implementations-42f6.md new file mode 100644 index 00000000000..4ece78074d0 --- /dev/null +++ b/.actual/rules/cross-cutting-mcp-server-implementations-42f6.md @@ -0,0 +1,43 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Mcp Server Implementations + +These rules are ALWAYS ACTIVE for all Android device MCP server implementations using the Model Context Protocol for AI model integration. + +### Rules + +- **R-MCP-001** MUST: MCP server implementations MUST import @modelcontextprotocol/sdk/server/index.js for server construction. +- **R-MCP-002** MUST: Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance. +- **R-MCP-003** MUST: Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing. +- **R-MCP-004** MUST: Implement tool error handling with console.error logging that includes tool name and error message. +- **R-MCP-005** MUST: Initialize server with name 'android-device-mcp' and version metadata in capability declarations. +- **R-MCP-006** MUST: Declare tools support in server capabilities during initialization. +- **R-MCP-007** SHOULD: Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity. + +### Verify + +```bash +# Verify SDK server imports +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . + +# Verify stdio transport imports +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify type definitions imports +grep -r "@modelcontextprotocol/sdk/types.js" --include="*.ts" --include="*.js" . + +# Verify tool error logging +grep -r "console.error" --include="*.ts" --include="*.js" . | grep -i "tool" + +# Verify capabilities declaration with tools support +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support and version metadata +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Tool implementations are organized in ./tools/ directory and validation utilities in ./utils/ directory + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-mcp-server-implementations-aae0.md b/.actual/rules/cross-cutting-mcp-server-implementations-aae0.md new file mode 100644 index 00000000000..65597320229 --- /dev/null +++ b/.actual/rules/cross-cutting-mcp-server-implementations-aae0.md @@ -0,0 +1,34 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Mcp Server Implementations + +These rules are ALWAYS ACTIVE for MCP server implementations using @modelcontextprotocol/sdk, including tool execution error handling, fatal error reporting, and stdio-based server communication. + +### Rules + +- **R-MCP-001** MUST: MCP server implementations MUST use console.error for logging tool execution errors with the format 'Tool error ({name}): {message}'. +- **R-MCP-002** MUST: MCP server implementations MUST import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities. +- **R-MCP-003** MUST: MCP server implementations MUST wrap tool execution in try-catch blocks and log errors using console.error with the specified format. +- **R-MCP-004** MUST: MCP server implementations MUST implement top-level error handlers for fatal errors using console.error('Fatal error:', error). +- **R-MCP-005** MUST: MCP server implementations MUST use stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr). + +### Verify + +```bash +# Verify tool error logging uses console.error with 'Tool error ({name}):' prefix +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal errors are logged with console.error using 'Fatal error:' prefix +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify server imports @modelcontextprotocol/sdk modules for server infrastructure +grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts +``` + +**Accept when:** +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure +- stdio transport is configured to separate protocol messages (stdout) from errors (stderr) + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for MCP server implementations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-mcp-servers-import-394d.md b/.actual/rules/cross-cutting-mcp-servers-import-394d.md new file mode 100644 index 00000000000..f511598055d --- /dev/null +++ b/.actual/rules/cross-cutting-mcp-servers-import-394d.md @@ -0,0 +1,35 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Mcp Servers Import + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, including tool execution error handling, fatal error reporting, and stdio-based server communication. + +### Rules + +- **R-MCP-001** MUST: MCP servers MUST import from @modelcontextprotocol/sdk/server/index.js, @modelcontextprotocol/sdk/server/stdio.js, and @modelcontextprotocol/sdk/types.js for server infrastructure. +- **R-MCP-002** MUST: All tool execution errors MUST be logged using console.error with the format 'Tool error ({toolName}): {error.message}'. +- **R-MCP-003** MUST: Fatal server errors MUST be logged using console.error with the format 'Fatal error: {error}'. +- **R-MCP-004** MUST: Tool execution MUST be wrapped in try-catch blocks with appropriate error logging. +- **R-MCP-005** MUST: The server MUST use stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr). + +### Verify + +```bash +# Verify @modelcontextprotocol/sdk imports are present +grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +# Verify tool error logging uses correct prefix +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal error logging uses correct prefix +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure +- Tool execution is wrapped in try-catch blocks +- stdio transport is configured from @modelcontextprotocol/sdk/server/stdio.js + + +Claude Code MUST NOT skip or defer verification. All grep-based verification commands MUST pass before accepting MCP server implementations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-memory-data-access-7a73.md b/.actual/rules/cross-cutting-memory-data-access-7a73.md new file mode 100644 index 00000000000..cfdd7160245 --- /dev/null +++ b/.actual/rules/cross-cutting-memory-data-access-7a73.md @@ -0,0 +1,41 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Memory Data Access + +These rules are ALWAYS ACTIVE for test specification files (*.spec.ts, *.test.ts), automation scripts in .github/scripts/, validation and parsing utilities, and CI/CD pipeline scripts. + +### Rules + +- **R-MEMORY-001** MUST: In-memory data access operations MUST use native collection methods (Array.find(), Set.add()) for querying and mutating data structures rather than introducing query abstraction libraries. +- **R-MEMORY-002** SHOULD: TypeScript test specifications SHOULD use vitest framework with describe/it structure and node:fs/node:path for file operations. +- **R-MEMORY-003** SHOULD: Python automation scripts SHOULD import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies. +- **R-MEMORY-004** SHOULD: Data access patterns SHOULD consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts. +- **R-MEMORY-005** MAY: Create shared utility modules for common patterns (parseJsonFile(), findInCollection(), addToSet()) to reduce duplication while maintaining standard library usage. + +### Verify + +```bash +# Verify vitest usage in TypeScript test files +grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l + +# Verify standard library file operations +grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l + +# Verify Python standard library imports only +grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l + +# Verify native collection method usage +grep -r "\.find(\|\.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +# Flag prohibited third-party imports in test/automation directories +grep -r "import.*lodash\|import.*ramda\|from.*lodash\|from.*ramda" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py +``` + +**Accept when:** +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts +- No prohibited third-party imports (lodash, ramda, etc.) are detected in test or automation script directories +- Shared utility modules follow standard library patterns without introducing external dependencies + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis MUST check for prohibited third-party imports in test and automation script directories. Code review MUST verify standard library usage for new test specifications and automation scripts. Pull requests adding external dependencies to automation scripts MUST require architecture review and explicit justification. Violations trigger CI build failure. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-navigation-lifecycle-events-3457.md b/.actual/rules/cross-cutting-navigation-lifecycle-events-3457.md new file mode 100644 index 00000000000..12be182f9d8 --- /dev/null +++ b/.actual/rules/cross-cutting-navigation-lifecycle-events-3457.md @@ -0,0 +1,35 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Navigation Lifecycle Events + +These rules are ALWAYS ACTIVE for all UI screens in the authentication feature module and new screen implementations across all feature modules within `app/src/main/kotlin/com/x8bit/bitwarden/ui/`. + +### Rules + +- **R-COMPOSE-001** SHOULD: Navigation and lifecycle events SHOULD use androidx.activity.compose utilities (BackHandler) when applicable. +- **R-COMPOSE-002** MUST: All screen files (*Screen.kt) in the ui/ module MUST contain at least one @Composable function. +- **R-COMPOSE-003** MUST: Layout composition MUST use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) rather than XML inflation. +- **R-COMPOSE-004** SHOULD: Separate screen composables from handler composables to maintain clear separation between UI composition and event handling logic. +- **R-COMPOSE-005** SHOULD: Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes. +- **R-COMPOSE-006** SHOULD: Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates. + +### Verify + +```bash +# Count @Composable annotations in ui module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout component usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope +- BackHandler is used for declarative back navigation handling in composable screens + + +Claude Code MUST NOT skip or defer verification. CI pipeline grep checks for @Composable annotation presence in *Screen.kt files are mandatory. Code review checklist verification of Compose usage in new UI implementations is required. Static analysis rules detecting XML layout inflation in new feature modules must pass. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-nested-field-access-e0d3.md b/.actual/rules/cross-cutting-nested-field-access-e0d3.md new file mode 100644 index 00000000000..d9061c489a8 --- /dev/null +++ b/.actual/rules/cross-cutting-nested-field-access-e0d3.md @@ -0,0 +1,34 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Nested Field Access + +These rules are ALWAYS ACTIVE for Python scripts in `.github/scripts/` that parse JSON responses from external APIs, integration test utilities that process configuration files with optional fields, and automation scripts that interact with GitHub API, JIRA API, or similar external services. + +### Rules + +- **R-NESTED-001** SHOULD: Nested field access SHOULD chain .get() calls (e.g., `response.get('fields', {}).get('field_name')`) to handle missing intermediate keys when accessing external API response fields. +- **R-NESTED-002** SHOULD: Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling. +- **R-NESTED-003** SHOULD: Add comments documenting why a field might be missing when using .get() for non-obvious cases. +- **R-NESTED-004** SHOULD: Consider logging at debug level when .get() returns a default value to aid troubleshooting. +- **R-NESTED-005** MUST: Use direct bracket notation only for guaranteed fields with documented justification in code comments. + +### Verify + +```bash +# Count .get() usage in integration scripts +grep -r '\.get(' .github/scripts/*.py | wc -l + +# Count direct bracket notation (potential violations) +grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l + +# Verify Python syntax +python -m py_compile .github/scripts/*.py +``` + +**Accept when:** +- Integration scripts in `.github/scripts/` use `.get()` for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields +- Nested field access chains `.get()` calls with appropriate default values for intermediate keys + + +Claude Code MUST NOT skip or defer verification. All integration scripts must be reviewed for compliance with nested field access patterns before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-numeric-coordinate-parameters-2d66.md b/.actual/rules/cross-cutting-numeric-coordinate-parameters-2d66.md new file mode 100644 index 00000000000..f34272840b5 --- /dev/null +++ b/.actual/rules/cross-cutting-numeric-coordinate-parameters-2d66.md @@ -0,0 +1,39 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Numeric Coordinate Parameters + +These rules are ALWAYS ACTIVE for all tool handler implementations in `src/tools/` that accept external input parameters from MCP clients. + +### Rules + +- **R-ZOD-001** MUST: Numeric coordinate parameters (x, y) MUST be validated as non-negative integers using `z.number().int().nonnegative()` +- **R-ZOD-002** MUST: All tool handlers accepting external parameters MUST import Zod at the top: `import { z } from 'zod'` +- **R-ZOD-003** MUST: All tool handlers accepting external parameters MUST import validation utilities: `import validation from '../utils/validation.js'` +- **R-ZOD-004** MUST: Input schemas MUST be defined as a const using `z.object()` with appropriate field validators before the handler function +- **R-ZOD-005** MUST: Timing parameters MUST be validated with `.min(0)` constraint +- **R-ZOD-006** SHOULD: Optional flags SHOULD use `.optional().default()` for sensible defaults +- **R-ZOD-007** SHOULD: TypeScript types SHOULD be exported using `z.infer` for use in function signatures +- **R-ZOD-008** SHOULD: Validation errors SHOULD be handled with clear, descriptive messages + +### Verify + +```bash +# Count Zod imports across tool handlers +grep -r "from 'zod'" src/tools/ | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/ | wc -l + +# Count validation utility imports +grep -r "../utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool handlers in `src/tools/` that accept external parameters import `'zod'` +- All relevant tool files define validation schemas using `z.object()` +- All relevant tool files import validation utilities from `'../utils/validation.js'` +- Coordinate parameters use `.int().nonnegative()` validation +- TypeScript compilation succeeds with type inference from schemas +- Code review confirms consistent schema patterns across implementations + + +Claude Code MUST NOT skip or defer verification. All tool handlers accepting external parameters MUST conform to these validation rules before merge. Violations are treated as blocking code review issues. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-numeric-inputs-include-ae1a.md b/.actual/rules/cross-cutting-numeric-inputs-include-ae1a.md new file mode 100644 index 00000000000..7bd3215eb32 --- /dev/null +++ b/.actual/rules/cross-cutting-numeric-inputs-include-ae1a.md @@ -0,0 +1,30 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Numeric Inputs Include + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-SCHEMA-001** SHOULD: Numeric inputs SHOULD include range constraints (min, max, nonnegative) and type constraints (int, float) appropriate to their domain. + +### Verify + +```bash +# Verify TypeScript tools use schema validation +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Verify Python scripts use json.load with validation +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions +- Numeric input schemas explicitly define type constraints (int, float) and range constraints (min, max, nonnegative) where applicable + + +Claude Code MUST NOT skip or defer verification. All new API endpoints accepting numeric inputs MUST include schema-based validation with explicit range and type constraints before processing. Pull requests introducing endpoints without such validation are blocked until validation is added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-numeric-inputs-representing-2f96.md b/.actual/rules/cross-cutting-numeric-inputs-representing-2f96.md new file mode 100644 index 00000000000..507b8ea724e --- /dev/null +++ b/.actual/rules/cross-cutting-numeric-inputs-representing-2f96.md @@ -0,0 +1,35 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Numeric Inputs Representing + +These rules are ALWAYS ACTIVE for all files matching the configured scope: tool handlers in android-device-server, XML parsing operations, GitHub automation scripts, public API contracts, and command-line argument parsing. + +### Rules + +- **R-VALIDATION-001** MUST: Numeric inputs representing coordinates or indices MUST be validated as non-negative integers using `z.number().int().nonnegative()` or equivalent constraints before processing. + +### Verify + +```bash +# Count zod schema definitions in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count fast-xml-parser usage in parsers +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Count json.load calls in GitHub scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation test suite +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints for numeric inputs before processing +- Numeric coordinate and index parameters use `z.number().int().nonnegative()` validation +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, zero values, missing optional fields, and malformed XML +- No unvalidated numeric inputs representing coordinates or indices reach business logic + + +Clause Code MUST NOT skip or defer verification of numeric input validation schemas. All pull requests introducing new API endpoints or tool handlers accepting numeric coordinates or indices MUST include zod schema definitions with non-negative integer constraints. Violations block code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-optional-parameters-declare-567e.md b/.actual/rules/cross-cutting-optional-parameters-declare-567e.md new file mode 100644 index 00000000000..dbf0508fff4 --- /dev/null +++ b/.actual/rules/cross-cutting-optional-parameters-declare-567e.md @@ -0,0 +1,30 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Optional Parameters Declare + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-SCHEMA-001** SHOULD: Optional parameters SHOULD declare explicit default values in the schema definition rather than handling defaults in business logic. + +### Verify + +```bash +# Verify schema validation presence in TypeScript tools +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Verify JSON parsing in Python scripts +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions +- Optional parameters in schemas explicitly declare default values using z.optional().default(value) or equivalent patterns + + +Claude Code MUST NOT skip or defer verification. All new API endpoints and modifications to existing endpoints must include schema-based validation with explicit default value declarations for optional parameters before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-optional-parameters-declare-8bf8.md b/.actual/rules/cross-cutting-optional-parameters-declare-8bf8.md new file mode 100644 index 00000000000..b8ca4bfedc2 --- /dev/null +++ b/.actual/rules/cross-cutting-optional-parameters-declare-8bf8.md @@ -0,0 +1,30 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Optional Parameters Declare + +These rules are ALWAYS ACTIVE for all tool handler implementations in `src/tools/` that accept external input parameters. + +### Rules + +- **R-ZOD-001** SHOULD: Optional parameters SHOULD declare default values using `.optional().default()` to simplify client usage. + +### Verify + +```bash +# Verify Zod imports are present in tool handlers +grep -r "from 'zod'" src/tools/ | wc -l + +# Verify z.object() schema definitions are used +grep -r "z\.object({" src/tools/ | wc -l + +# Verify validation utility imports are present +grep -r "../utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool handlers in `src/tools/` that accept external parameters import `'zod'` and define validation schemas +- Grep commands show consistent usage of `z.object()` schema definitions across tool implementations +- Validation utility imports from `'../utils/validation.js'` are present in all relevant tool files +- Optional parameters use `.optional().default()` pattern for sensible defaults + + +Clause Code MUST NOT skip or defer verification. All tool handlers accepting external input MUST conform to this schema validation pattern with explicit default declarations for optional parameters. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-pattern-matching-against-b313.md b/.actual/rules/cross-cutting-pattern-matching-against-b313.md new file mode 100644 index 00000000000..af276c4433a --- /dev/null +++ b/.actual/rules/cross-cutting-pattern-matching-against-b313.md @@ -0,0 +1,29 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Pattern Matching Against + +These rules are ALWAYS ACTIVE for GitHub pull request labeling automation scripts and external client boundary interactions requiring pattern-driven label management. + +### Rules + +- **R-LABEL-001** MUST: Pattern matching against title_patterns and path_patterns MUST be performed before label addition. + +### Verify + +```bash +# Detect set-based label accumulation patterns +grep -r '\.add("app:' .github/scripts/ | wc -l + +# Verify set initialization +grep -r 'labels.*=.*set()' .github/scripts/ | wc -l + +# Validate Python syntax +python3 -m py_compile .github/scripts/label-pr.py +``` + +**Accept when:** +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + + +Claude Code MUST NOT skip or defer verification. Pattern matching must precede all label additions to prevent invalid labels from being applied to pull requests. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-predicate-functions-passed-fc06.md b/.actual/rules/cross-cutting-predicate-functions-passed-fc06.md new file mode 100644 index 00000000000..c7f9dcaaad5 --- /dev/null +++ b/.actual/rules/cross-cutting-predicate-functions-passed-fc06.md @@ -0,0 +1,29 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Predicate Functions Passed + +These rules are ALWAYS ACTIVE for all TypeScript, JavaScript, and Python files that perform in-memory data queries on collections, particularly when working with parsed system output, configuration data, and test fixtures. + +### Rules + +- **R-COLL-001** MUST: Predicate functions passed to `.find()` must test for property equality using strict comparison (`===`) or property name matching. + +### Verify + +```bash +# Verify Array.find() usage with predicate functions in TypeScript/JavaScript +grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . + +# Verify Set.add() usage for collection building in Python +grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' + +# Verify test suite passes for dumpsys parser with window lookup operations +npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' +``` + +**Accept when:** +- Grep commands identify at least 3 instances of `Array.find()` with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate `Set.add()` usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using `.find()` method + + +Clause Code MUST NOT skip or defer verification. All three verification commands must pass before accepting changes that introduce or modify collection query patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-action-contracts-270f.md b/.actual/rules/cross-cutting-public-action-contracts-270f.md new file mode 100644 index 00000000000..a1987304629 --- /dev/null +++ b/.actual/rules/cross-cutting-public-action-contracts-270f.md @@ -0,0 +1,36 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Public Action Contracts + +These rules are ALWAYS ACTIVE for all Android ViewModels serving as public API boundaries for system integrations, including credential provider APIs, authentication callback Intents, and autofill service interactions. + +### Rules + +- **R-HILT-001** MUST: Public API action contracts MUST be expressed as sealed classes or interfaces to enforce type-safe event handling. +- **R-HILT-002** MUST: All ViewModels handling Intent-based public API interactions MUST be annotated with @HiltViewModel. +- **R-HILT-003** MUST: Public API ViewModels MUST inject dependencies through constructor parameters annotated with @Inject. +- **R-HILT-004** MUST: Public API ViewModels MUST extend BaseViewModel and define sealed action types for Intent processing contracts. +- **R-HILT-005** SHOULD: Repository or manager layer components SHOULD be used for Intent processing logic rather than embedding Android framework calls directly in ViewModel. +- **R-HILT-006** SHOULD: Unit tests for ViewModels SHOULD use Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies. + +### Verify + +```bash +# Verify @HiltViewModel annotation on public API boundary ViewModels +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l + +# Verify sealed action types are defined +grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l + +# Verify public API ViewModels extend BaseViewModel and use @HiltViewModel +find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l +``` + +**Accept when:** +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters +- Constructor parameters are annotated with @Inject +- No public API ViewModels lack @HiltViewModel annotation + + +Clause Code MUST NOT skip or defer verification. All public API boundary ViewModels must comply with R-HILT-001 through R-HILT-006 before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-contract-functions-0f60.md b/.actual/rules/cross-cutting-public-contract-functions-0f60.md new file mode 100644 index 00000000000..6648b75433b --- /dev/null +++ b/.actual/rules/cross-cutting-public-contract-functions-0f60.md @@ -0,0 +1,35 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Public Contract Functions + +These rules are ALWAYS ACTIVE for all GitHub automation scripts in `.github/scripts/` that interact with GitHub APIs and configuration management. + +### Rules + +- **R-PUBCON-001** MUST: Public contract functions MUST handle JSON parsing errors with explicit exception handling (json.JSONDecodeError) and provide meaningful error context. +- **R-PUBCON-002** MUST: All GitHub API interaction functions MUST follow the naming convention prefix 'gh_' to clearly mark the integration boundary and distinguish from internal helper functions. +- **R-PUBCON-003** MUST: Configuration file parsing MUST use json.load() with explicit try/except json.JSONDecodeError exception handling. +- **R-PUBCON-004** MUST: GitHub API interactions MUST use subprocess invocation of gh CLI rather than direct HTTP client libraries. +- **R-PUBCON-005** SHOULD: Label manipulation SHOULD use Python sets for deduplication, converting to lists only when calling gh CLI commands. +- **R-PUBCON-006** SHOULD: Subprocess calls SHOULD capture both stdout and stderr, logging errors with context about which gh command failed. + +### Verify + +```bash +# Verify GitHub integration functions follow naming convention and are discoverable +grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py + +# Verify JSON parsing includes explicit exception handling for JSONDecodeError +grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py + +# Verify GitHub API interactions use subprocess invocation of gh CLI +grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py +``` + +**Accept when:** +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries +- Function contracts are stable and testable without requiring live API access + + +Claude Code MUST NOT skip or defer verification of these rules. All public contract functions in GitHub automation scripts MUST comply with naming conventions, exception handling patterns, and subprocess-based gh CLI invocation requirements before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-contracts-exported-2e18.md b/.actual/rules/cross-cutting-public-contracts-exported-2e18.md new file mode 100644 index 00000000000..41d194e4477 --- /dev/null +++ b/.actual/rules/cross-cutting-public-contracts-exported-2e18.md @@ -0,0 +1,41 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Public Contracts Exported + +These rules are ALWAYS ACTIVE for all public API tool handlers in `src/tools/` that expose contracts to external callers, requiring consistent input validation, asynchronous execution patterns, and named exports. + +### Rules + +- **R-ASYNC-ZOD-001** MUST: Public API contracts MUST be exported as named exports (e.g., capture, tapAt, FindElementResult, findElementWithObstruction). +- **R-ASYNC-ZOD-002** MUST: All tool files in `src/tools/` that expose public API handlers MUST import Zod at the top: `import { z } from 'zod'`. +- **R-ASYNC-ZOD-003** MUST: All public API handlers (capture, tapAt, findElementWithObstruction) MUST be declared as async functions. +- **R-ASYNC-ZOD-004** MUST: Validation schemas MUST be defined as const objects before handler functions using `z.object()` with field-level constraints. +- **R-ASYNC-ZOD-005** MUST: Input validation MUST occur at the entry point of each handler using `schema.parse()` or `schema.safeParse()` before proceeding with handler logic. +- **R-ASYNC-ZOD-006** MUST: All async handlers MUST properly await ADB operations and filesystem calls, and wrap execution in try/catch for error handling. +- **R-ASYNC-ZOD-007** SHOULD: Use Zod's `z.infer<>` utility to derive TypeScript types from schemas, ensuring single source of truth and preventing schema drift. +- **R-ASYNC-ZOD-008** SHOULD: Wrap Zod validation errors in error handling that transforms them into user-friendly messages with field-level details. + +### Verify + +```bash +# Count Zod imports across tool files +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l + +# Verify named exports for public contracts +grep -r "export.*\(capture\|tapAt\|FindElementResult\|findElementWithObstruction\)" src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` import Zod and define at least one `z.object()` schema. +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions. +- Verification commands show consistent usage of Zod schemas across at least 3 tool files. +- Public API contracts are exported as named exports with clear API boundaries. +- Validation occurs at handler entry points before execution logic proceeds. + + +Claude Code MUST NOT skip or defer verification. All tool handlers exposing public API contracts MUST satisfy R-ASYNC-ZOD-001 through R-ASYNC-ZOD-006 before code review approval. Violations are P1 bugs requiring immediate schema addition. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-endpoints-that-0acc.md b/.actual/rules/cross-cutting-public-endpoints-that-0acc.md new file mode 100644 index 00000000000..5c7beaf896f --- /dev/null +++ b/.actual/rules/cross-cutting-public-endpoints-that-0acc.md @@ -0,0 +1,29 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Public Endpoints That + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-SCHEMA-001** MUST: All public API endpoints that accept external input MUST validate input using a schema validation library (zod for TypeScript, json.load with schema validation for Python) before processing. + +### Verify + +```bash +# Count schema validation usage in TypeScript tools +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Count JSON loading in Python scripts +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + + +Claude Code MUST NOT skip or defer verification. All public API endpoints must be validated using schema-based libraries before merging. Pull requests introducing API endpoints without validation are blocked until validation is added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-endpoints-tool-48f1.md b/.actual/rules/cross-cutting-public-endpoints-tool-48f1.md new file mode 100644 index 00000000000..1951c07f680 --- /dev/null +++ b/.actual/rules/cross-cutting-public-endpoints-tool-48f1.md @@ -0,0 +1,41 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Public Endpoints Tool + +These rules are ALWAYS ACTIVE for all public API endpoints, tool handlers, XML parsing operations, and external input processing across TypeScript and Python modules in the android-device-server MCP components and GitHub automation scripts. + +### Rules + +- **R-VALIDATION-001** MUST: All public API endpoints and tool handlers MUST validate input parameters using zod schemas with explicit type constraints (z.number(), z.boolean(), z.string()) before processing. +- **R-VALIDATION-002** MUST: XML parsing operations MUST use fast-xml-parser with appropriate error handling configuration to prevent injection attacks and malformed data propagation. +- **R-VALIDATION-003** MUST: JSON configuration loading in Python modules MUST wrap json.load() calls in try-except blocks and validate required fields exist before accessing. +- **R-VALIDATION-004** MUST: Validation schemas MUST be defined adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters. +- **R-VALIDATION-005** MUST: All validation errors MUST be sanitized to prevent information disclosure, mapping internal validation errors to generic user-facing messages while logging detailed errors internally. +- **R-VALIDATION-006** SHOULD: Use the validateInput utility from utils/validation.ts to apply schemas consistently across tool handlers, ensuring uniform error handling. +- **R-VALIDATION-007** SHOULD: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases on high-frequency API endpoints. + +### Verify + +```bash +# Count zod schema definitions in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count fast-xml-parser usage in parsers +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Count json.load() calls in Python scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation test suite +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML +- Error responses for invalid inputs are consistent across all public APIs +- No unvalidated external inputs are detected in code review + + +Clause Code MUST NOT skip or defer verification of these rules. All public API endpoints and external input processing MUST comply with R-VALIDATION-001 through R-VALIDATION-007 before merge. Security team review is required for any exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-test-contracts-600b.md b/.actual/rules/cross-cutting-public-test-contracts-600b.md new file mode 100644 index 00000000000..9f8afb24560 --- /dev/null +++ b/.actual/rules/cross-cutting-public-test-contracts-600b.md @@ -0,0 +1,42 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Public Test Contracts + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that validate JSON structure, configuration, or CI/CD artifacts, and for integration tests that validate public API contracts of utility functions. + +### Rules + +- **R-UTC-001** MUST: Public test contracts MUST be expressed as methods prefixed with `test_` that describe the behavior being validated. +- **R-UTC-002** MUST: All test classes that use fixtures MUST implement both `setUp` and `tearDown` methods for test isolation and resource cleanup. +- **R-UTC-003** MUST: Test methods MUST include docstrings that explain what contract or behavior is being validated. +- **R-UTC-004** SHOULD: Store test fixtures in a `fixtures/` subdirectory adjacent to test files, using descriptive names (e.g., `sample-valid1.json`, `sample-invalid.json`). +- **R-UTC-005** SHOULD: Construct fixture paths using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-UTC-006** SHOULD: Use `patch('sys.stdout', new=io.StringIO())` in `setUp` and `stop` in `tearDown` to suppress output from CLI utilities during testing. +- **R-UTC-007** SHOULD: Name test methods with `test_` prefix followed by descriptive names that communicate the contract being validated (e.g., `test_validate_json_valid`, `test_find_duplicates_returns_empty_list_when_no_duplicates`). +- **R-UTC-008** MAY: Use `setUpClass`/`tearDownClass` for shared fixtures across all test methods when fixture initialization is expensive and tests can safely share state without pollution risk. + +### Verify + +```bash +# Verify all test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp methods are implemented +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown methods are implemented +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run all tests via unittest discovery +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via unittest discovery +- Fixture paths are constructed using `os.path.join(os.path.dirname(__file__), ...)` +- Test method names clearly describe the contract or behavior being validated + + +Claude Code MUST NOT skip or defer verification. All test files in `.github/scripts/` MUST follow these rules. CI pipeline MUST run unittest discovery on all `test_*.py` files. Code review MUST verify `setUp`/`tearDown` implementation for new test classes. Violations block merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-tool-handlers-deff.md b/.actual/rules/cross-cutting-public-tool-handlers-deff.md new file mode 100644 index 00000000000..8da6769fb5c --- /dev/null +++ b/.actual/rules/cross-cutting-public-tool-handlers-deff.md @@ -0,0 +1,37 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Public Tool Handlers + +These rules are ALWAYS ACTIVE for all public API tool handlers in `src/tools/` that expose contracts for capture, tapAt, findElementWithObstruction, and similar external-process-coordinating functions. + +### Rules + +- **R-HANDLER-001** MUST: All public API tool handlers MUST use Zod schemas to validate input parameters before execution. +- **R-HANDLER-002** MUST: All public API tool handlers MUST be declared as async functions to enable non-blocking coordination with ADB processes and filesystem operations. +- **R-HANDLER-003** MUST: Validation schemas MUST be defined as const objects using `z.object()` before handler functions in the same module. +- **R-HANDLER-004** MUST: Zod MUST be imported at the top of each tool module: `import { z } from 'zod'`. +- **R-HANDLER-005** MUST: All async handlers MUST properly await ADB operations and filesystem calls, and wrap in try/catch for error handling. +- **R-HANDLER-006** MUST: Handler entry points MUST call `schema.parse()` or `schema.safeParse()` to validate inputs before proceeding with business logic. +- **R-HANDLER-007** SHOULD: Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers. +- **R-HANDLER-008** SHOULD: Use Zod's `z.infer<>` utility to derive TypeScript types from schemas, ensuring single source of truth and preventing schema drift. + +### Verify + +```bash +# Count Zod imports across tool files +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` import Zod and define at least one `z.object()` schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files +- No public API tool handler exists without Zod validation at its entry point + + +Clause Code MUST NOT skip or defer verification. Pull requests adding new tools without Zod validation are blocked until schemas are added. Existing tools without validation must be flagged for refactoring in technical debt backlog. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-python-automation-scripts-7c5d.md b/.actual/rules/cross-cutting-python-automation-scripts-7c5d.md new file mode 100644 index 00000000000..139298b8548 --- /dev/null +++ b/.actual/rules/cross-cutting-python-automation-scripts-7c5d.md @@ -0,0 +1,37 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Python Automation Scripts + +These rules are ALWAYS ACTIVE for all Python automation scripts in `.github/scripts/`, test specifications (*.spec.ts, *.test.ts), validation and parsing utilities, and CI/CD pipeline scripts. + +### Rules + +- **R-PYAUTO-001** MUST: Python automation scripts MUST use standard library modules (json, sys, os, argparse) for file I/O, argument parsing, and JSON processing rather than external dependencies. +- **R-PYAUTO-002** MUST: Python automation scripts MUST NOT import third-party collection libraries (lodash, ramda, pandas, etc.) for data manipulation in test and automation contexts. +- **R-PYAUTO-003** SHOULD: Data access patterns SHOULD use native collection methods (find(), add(), json.load()) rather than abstraction layers for low-complexity query operations. +- **R-PYAUTO-004** SHOULD: Shared utility modules SHOULD be created for common patterns (parseJsonFile(), findInCollection(), addToSet()) to reduce duplication while maintaining standard library usage. +- **R-PYAUTO-005** MAY: External dependencies MAY be used only when performance profiling indicates native collection methods create bottlenecks in large dataset processing, or when external API contracts require specific JSON schema validation beyond standard json module capabilities. + +### Verify + +```bash +# Verify Python automation scripts use only standard library imports +grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l + +# Verify no prohibited third-party imports in automation scripts +grep -r "import lodash\|import ramda\|import pandas\|from lodash\|from ramda\|from pandas" .github/scripts/**/*.py | wc -l + +# Verify data access patterns use native methods +grep -r "\.find(\|\.add(\|json\.load" .github/scripts/**/*.py | wc -l + +# Verify no external dependencies in requirements.txt for automation scripts +grep -v "^#" .github/scripts/requirements.txt 2>/dev/null | grep -v "^$" | wc -l +``` + +**Accept when:** +- All Python automation scripts in `.github/scripts/` import only standard library modules (json, sys, os, argparse) for core functionality +- No prohibited third-party imports (lodash, ramda, pandas, etc.) are detected in automation script directories +- Data access patterns consistently use native collection methods (find(), add(), json.load()) across automation contexts +- Any external dependencies are explicitly documented with justification referencing performance benchmarks or capability gaps + + +Claude Code MUST NOT skip or defer verification of these rules. All Python automation scripts MUST comply with R-PYAUTO-001 and R-PYAUTO-002 before merge. Violations trigger CI build failure and require architecture review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-python-test-classes-6e3e.md b/.actual/rules/cross-cutting-python-test-classes-6e3e.md new file mode 100644 index 00000000000..dd423a8ef4e --- /dev/null +++ b/.actual/rules/cross-cutting-python-test-classes-6e3e.md @@ -0,0 +1,33 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Python Test Classes + +These rules are ALWAYS ACTIVE for all Python test files with `test_` prefix or `_test` suffix, and all TypeScript test files with `.spec.ts` or `.test.ts` extensions. + +### Rules + +- **R-UNITTEST-001** SHOULD: Python test classes SHOULD implement setUp and tearDown methods for test fixture initialization and cleanup when shared state is required. + +### Verify + +```bash +# Verify unittest imports in Python test files +grep -r 'import unittest' --include='test_*.py' .github/scripts/ + +# Verify vitest imports in TypeScript test files +grep -r 'from vitest import' --include='*.spec.ts' .claude/ + +# Verify unittest.TestCase inheritance in Python tests +grep -r 'class.*unittest\.TestCase' --include='test_*.py' . + +# Verify describe/it structure in TypeScript tests +grep -r 'describe\|it' --include='*.spec.ts' . +``` + +**Accept when:** +- All Python test files contain `import unittest` and define classes inheriting from `unittest.TestCase` +- All TypeScript test files with `.spec.ts` extension import from `vitest` and use `describe/it` structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results +- Python test classes implement `setUp` and `tearDown` methods for fixture management when shared state is required + + +Claude Code MUST NOT skip or defer verification. All Python test classes SHOULD follow the setUp/tearDown pattern for fixture initialization and cleanup. Violations must be flagged during code review and CI pipeline execution. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-python-test-files-de0b.md b/.actual/rules/cross-cutting-python-test-files-de0b.md new file mode 100644 index 00000000000..c3e098f8226 --- /dev/null +++ b/.actual/rules/cross-cutting-python-test-files-de0b.md @@ -0,0 +1,39 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Python Test Files + +These rules are ALWAYS ACTIVE for all Python test files with `test_` prefix or `_test` suffix, and all TypeScript test files with `.spec.ts` or `.test.ts` extensions. + +### Rules + +- **R-TEST-001** MUST: Python test files MUST use unittest as the test framework with unittest.TestCase as the base class for test suites. +- **R-TEST-002** MUST: Python test files MUST import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with `test_`. +- **R-TEST-003** MUST: TypeScript test files MUST import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping. +- **R-TEST-004** SHOULD: Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management. +- **R-TEST-005** SHOULD: Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks. +- **R-TEST-006** MAY: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable (EXC-001). +- **R-TEST-007** MAY: Specialized testing scenarios may use framework-specific features not available in unittest or vitest with documented exception (EXC-002). + +### Verify + +```bash +# Verify Python test files use unittest +grep -r 'import unittest' --include='test_*.py' .github/scripts/ +grep -r 'class.*unittest\.TestCase' --include='test_*.py' . + +# Verify TypeScript test files use vitest +grep -r 'from vitest import' --include='*.spec.ts' .claude/ +grep -r 'describe\|it' --include='*.spec.ts' . + +# Verify test execution in CI +# Python unittest discovery with 'test_*.py' pattern +# vitest configuration for '*.spec.ts' files +``` + +**Accept when:** +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results +- No plain assert statements are used in unittest.TestCase classes (detected via linting) + + +Clause Code MUST NOT skip or defer verification. CI pipeline test execution MUST require unittest and vitest as test runners. Code review MUST verify test framework compliance for new test files. Static analysis linting rules MUST detect non-compliant test patterns. CI build MUST fail if tests cannot be discovered or executed by the specified framework. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-python-test-methods-8229.md b/.actual/rules/cross-cutting-python-test-methods-8229.md new file mode 100644 index 00000000000..e2c55f517e9 --- /dev/null +++ b/.actual/rules/cross-cutting-python-test-methods-8229.md @@ -0,0 +1,39 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Python Test Methods + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/*/test_*.py` and TypeScript test files in `.claude/mcp/**/src/**/*.spec.ts`. + +### Rules + +- **R-TEST-001** MUST: Python test methods MUST follow the `test_*` naming convention. +- **R-TEST-002** MUST: All Python test files MUST use `unittest.TestCase` as the base class for test classes. +- **R-TEST-003** MUST: All TypeScript test files MUST use vitest with `describe`/`it` structure and `*.spec.ts` naming convention. +- **R-TEST-004** MUST: Test fixtures MUST be organized in dedicated `fixtures/` directories relative to test files. +- **R-TEST-005** SHOULD: Python tests SHOULD use `setUp`/`tearDown` lifecycle methods for resource initialization and cleanup. +- **R-TEST-006** SHOULD: TypeScript tests SHOULD use `beforeEach`/`afterEach` for test lifecycle management. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase and test_* naming +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests use vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files to ensure coverage +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +# Verify test file naming conventions +find .github/scripts -name 'test_*.py' -type f +find .claude/mcp -name '*.spec.ts' -type f +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class and `test_*` method naming convention +- All TypeScript test files use vitest with `describe`/`it` structure and `*.spec.ts` naming convention +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- No test files exist outside the configured scope using non-standard frameworks or naming conventions + + +Claude Code MUST NOT skip or defer verification. All test files MUST conform to the specified frameworks and naming conventions before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-python-test-modules-e4ca.md b/.actual/rules/cross-cutting-python-test-modules-e4ca.md new file mode 100644 index 00000000000..5c9d0aae195 --- /dev/null +++ b/.actual/rules/cross-cutting-python-test-modules-e4ca.md @@ -0,0 +1,45 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Python Test Modules + +These rules are ALWAYS ACTIVE for all Python test modules in `.github/scripts/*/test_*.py` and TypeScript test modules in `.claude/mcp/**/src/**/*.spec.ts`. + +### Rules + +- **R-TEST-001** MUST: Python test modules MUST use `unittest.TestCase` as the base class for test organization. +- **R-TEST-002** MUST: Python test methods MUST be prefixed with `test_` and organized within classes inheriting from `unittest.TestCase`. +- **R-TEST-003** MUST: TypeScript test modules MUST use vitest with `describe` and `it` block structure for organizing test suites and individual test cases. +- **R-TEST-004** MUST: TypeScript test files MUST follow the `*.spec.ts` naming convention. +- **R-TEST-005** MUST: Test fixtures MUST be organized in dedicated `fixtures/` subdirectories relative to test files. +- **R-TEST-006** SHOULD: Python tests SHOULD use `setUp`/`tearDown` lifecycle methods for test initialization and cleanup. +- **R-TEST-007** SHOULD: TypeScript tests SHOULD use `beforeEach`/`afterEach` for test lifecycle management including resource initialization and cleanup. +- **R-TEST-008** SHOULD: Test fixtures SHOULD be loaded using `os.path.join` (Python) or `node:path` (TypeScript) for proper path resolution. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests import from vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count total test files +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +# Verify test file naming conventions +find .github/scripts -name 'test_*.py' | wc -l +find .claude/mcp -name '*.spec.ts' | wc -l + +# Verify fixtures directory structure +find . -type d -name 'fixtures' | grep -E '(test_|spec)' +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class and `test_*` method naming convention +- All TypeScript test files use vitest with `describe`/`it` structure and `*.spec.ts` naming convention +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- Python tests use `setUp`/`tearDown` for lifecycle management +- TypeScript tests use `beforeEach`/`afterEach` for lifecycle management + + +Claude Code MUST NOT skip or defer verification of these rules during code review and CI pipeline execution. Pull requests introducing tests with non-standard frameworks or naming conventions MUST be rejected. CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites MUST succeed. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-python-tests-use-cfac.md b/.actual/rules/cross-cutting-python-tests-use-cfac.md new file mode 100644 index 00000000000..44e469676eb --- /dev/null +++ b/.actual/rules/cross-cutting-python-tests-use-cfac.md @@ -0,0 +1,36 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Python Tests Use + +These rules are ALWAYS ACTIVE for all Python test files with `test_` prefix or `_test` suffix, and all TypeScript test files with `.spec.ts` or `.test.ts` extensions. + +### Rules + +- **R-UNITTEST-001** MUST: Python tests MUST use unittest assertion methods (assertTrue, assertFalse, assertEqual, assertIn) rather than plain assert statements. +- **R-UNITTEST-002** MUST: Python test files MUST import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with `test_`. +- **R-VITEST-001** MUST: TypeScript test files MUST import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping. +- **R-UNITTEST-003** SHOULD: Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management. +- **R-UNITTEST-004** SHOULD: Follow naming conventions with descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks. + +### Verify + +```bash +# Verify Python test files use unittest +grep -r 'import unittest' --include='test_*.py' .github/scripts/ +grep -r 'class.*unittest\.TestCase' --include='test_*.py' . + +# Verify TypeScript test files use vitest +grep -r 'from vitest import' --include='*.spec.ts' .claude/ +grep -r 'describe\|it' --include='*.spec.ts' . + +# Verify no plain assert statements in unittest test classes +grep -r 'assert ' --include='test_*.py' . | grep -v 'assertTrue\|assertFalse\|assertEqual\|assertIn\|assertRaises\|assertIsNone' +``` + +**Accept when:** +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results +- No plain assert statements are found in unittest.TestCase classes (only unittest assertion methods are used) + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for code review and CI pipeline enforcement. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-real-time-integration-d898.md b/.actual/rules/cross-cutting-real-time-integration-d898.md new file mode 100644 index 00000000000..51deec61271 --- /dev/null +++ b/.actual/rules/cross-cutting-real-time-integration-d898.md @@ -0,0 +1,36 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Real Time Integration + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services. + +### Rules + +- **R-RTDI-001** MUST: Real-time integration servers MUST use the Model Context Protocol SDK (@modelcontextprotocol/sdk/server/index.js) as the foundation for server implementation. +- **R-RTDI-002** MUST: Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation. +- **R-RTDI-003** MUST: Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests. +- **R-RTDI-004** MUST: Organize tool implementations in separate modules and maintain a registry for runtime lookup. +- **R-RTDI-005** MUST: Implement validation utilities to verify tool parameters before execution and provide clear error messages. +- **R-RTDI-006** SHOULD: Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs. +- **R-RTDI-007** SHOULD: Implement connection pooling and measure concurrent connection limits in load testing to address stdio transport scalability concerns. +- **R-RTDI-008** MAY: Migrate tool lookup from runtime search to Map-based lookup if tool count exceeds 50 to optimize performance. + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization with capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic using collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk imports, code review checklist verification of capabilities declaration, and integration tests verifying tool discovery are mandatory before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-schema-definitions-specify-ed0c.md b/.actual/rules/cross-cutting-schema-definitions-specify-ed0c.md new file mode 100644 index 00000000000..71ec041bbcc --- /dev/null +++ b/.actual/rules/cross-cutting-schema-definitions-specify-ed0c.md @@ -0,0 +1,31 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Schema Definitions Specify + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-SCHEMA-001** MUST: Schema definitions MUST specify type constraints, required fields, and acceptable value ranges using the validation library's type system (z.object, z.number, z.boolean, etc.) + +### Verify + +```bash +# Count schema validation usage in TypeScript tools +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Count JSON parsing in Python scripts +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions +- For TypeScript tools, validation schemas are defined using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) +- For Python scripts, json.load() is used with subsequent schema validation or a Python schema validation library (pydantic, marshmallow) + + +Claude Code MUST NOT skip or defer verification. All public API endpoints accepting external input MUST include schema-based validation before processing. Pull requests introducing API endpoints without validation are blocked until validation is added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-screen-composables-use-3522.md b/.actual/rules/cross-cutting-screen-composables-use-3522.md new file mode 100644 index 00000000000..4972b733f11 --- /dev/null +++ b/.actual/rules/cross-cutting-screen-composables-use-3522.md @@ -0,0 +1,39 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Screen Composables Use + +These rules are ALWAYS ACTIVE for all UI screen files in the app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy, authentication feature screens, handlers, and new screen implementations across all feature modules. + +### Rules + +- **R-COMPOSE-001** MUST: Screen composables MUST use androidx.compose.foundation.layout components (Column, Row, Spacer, fillMaxSize, fillMaxWidth) for layout structure. +- **R-COMPOSE-002** MUST: All screen files (*Screen.kt) in the ui/ module MUST contain at least one @Composable function. +- **R-COMPOSE-003** MUST: Layout composition MUST use androidx.compose.foundation.layout components rather than XML inflation. +- **R-COMPOSE-004** MUST: New screen implementations MUST NOT create XML layout files in feature modules covered by this ADR scope. +- **R-COMPOSE-005** SHOULD: Separate screen composables from handler composables to maintain clear separation between UI composition and event handling logic. +- **R-COMPOSE-006** SHOULD: Use androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes. +- **R-COMPOSE-007** SHOULD: Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates. +- **R-COMPOSE-008** SHOULD: Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens. + +### Verify + +```bash +# Count @Composable annotations in UI module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope +- CI pipeline grep checks confirm @Composable annotation presence in *Screen.kt files +- Code review verification confirms Compose usage in new UI implementations +- Static analysis rules detect no XML layout inflation in new feature modules + + +Claude Code MUST NOT skip or defer verification. All screen files must be checked for @Composable annotations and proper use of androidx.compose.foundation.layout components. CI build warnings MUST be issued for violations, and code review rejection is required for XML-based layouts in new feature development. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-screen-implementations-separate-575c.md b/.actual/rules/cross-cutting-screen-implementations-separate-575c.md new file mode 100644 index 00000000000..fbff611de13 --- /dev/null +++ b/.actual/rules/cross-cutting-screen-implementations-separate-575c.md @@ -0,0 +1,36 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Screen Implementations Separate + +These rules are ALWAYS ACTIVE for all UI screen implementations in the `app/src/main/kotlin/com/x8bit/bitwarden/ui/` module hierarchy and new screen implementations across all feature modules. + +### Rules + +- **R-COMPOSE-001** SHOULD: Screen implementations SHOULD separate UI composition (Screen composables) from event handling logic (Handler composables). +- **R-COMPOSE-002** MUST: All screen files (*Screen.kt) in the ui/ module MUST contain at least one @Composable function. +- **R-COMPOSE-003** SHOULD: Layout composition SHOULD use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required. +- **R-COMPOSE-004** SHOULD: Screen composables SHOULD leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes. +- **R-COMPOSE-005** SHOULD: Screen implementations SHOULD integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates. +- **R-COMPOSE-006** SHOULD: Screen implementations SHOULD use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens. +- **R-COMPOSE-007** MUST: No new XML layout files MUST be created in feature modules covered by this ADR scope. + +### Verify + +```bash +# Count @Composable annotations in UI module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout component usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope +- Screen implementations demonstrate clear separation between UI composition and event handling logic + + +Claude Code MUST NOT skip or defer verification. All screen implementations MUST be checked for @Composable annotations and proper composition patterns before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-screen-implementations-use-73df.md b/.actual/rules/cross-cutting-screen-implementations-use-73df.md new file mode 100644 index 00000000000..3f74df5a6c1 --- /dev/null +++ b/.actual/rules/cross-cutting-screen-implementations-use-73df.md @@ -0,0 +1,39 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Screen Implementations Use + +These rules are ALWAYS ACTIVE for all UI screen implementations in the `app/src/main/kotlin/com/x8bit/bitwarden/ui/` module hierarchy and all new screen implementations across feature modules. + +### Rules + +- **R-COMPOSE-001** MUST: All UI screen implementations MUST use `@Composable` functions as the primary unit of UI composition. +- **R-COMPOSE-002** MUST: Layout composition MUST use `androidx.compose.foundation.layout` components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required. +- **R-COMPOSE-003** MUST: Screen composables (e.g., SetupUnlockScreen) MUST be separated from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic. +- **R-COMPOSE-004** SHOULD: Leverage `androidx.compose.runtime.remember` for state that should survive recomposition and `androidx.compose.runtime.rememberSaveable` for state that should survive configuration changes. +- **R-COMPOSE-005** SHOULD: Integrate with ViewModel using `androidx.lifecycle.viewmodel.compose.viewModel()` and observe state using `collectAsState()` for reactive UI updates. +- **R-COMPOSE-006** SHOULD: Use `androidx.activity.compose.BackHandler` for declarative back navigation handling within composable screens. +- **R-COMPOSE-007** MUST NOT: New XML layout files MUST NOT be created in feature modules covered by this ADR scope. + +### Verify + +```bash +# Count @Composable functions in UI module +grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l + +# Count androidx.compose.foundation.layout component usage +grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l + +# Find screen files without @Composable annotation +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +# Detect new XML layout files in feature modules +find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*.xml' -type f +``` + +**Accept when:** +- All screen files (`*Screen.kt`) in the `ui/` module contain at least one `@Composable` function +- Layout composition uses `androidx.compose.foundation.layout` components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope +- Screen and handler composables are logically separated with clear responsibility boundaries + + +Claude Code MUST NOT skip or defer verification. All new UI screen implementations MUST be verified against these rules before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-screen-level-implementations-c0e0.md b/.actual/rules/cross-cutting-screen-level-implementations-c0e0.md new file mode 100644 index 00000000000..94d16297abc --- /dev/null +++ b/.actual/rules/cross-cutting-screen-level-implementations-c0e0.md @@ -0,0 +1,35 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Screen Level Implementations + +These rules are ALWAYS ACTIVE for all Android UI screen implementations in app/src/main/kotlin UI packages, authentication feature module UI components, and any function that directly or indirectly emits Compose UI elements. + +### Rules + +- **R-COMPOSE-001** MUST: Screen-level UI implementations MUST use androidx.compose.foundation.layout components (Column, Row, Spacer, etc.) for layout composition. +- **R-COMPOSE-002** MUST: All UI component files that emit visual elements MUST include the @Composable annotation on functions that compose UI. +- **R-COMPOSE-003** MUST: Import androidx.compose.runtime.Composable explicitly in all UI component files. +- **R-COMPOSE-004** SHOULD: Use androidx.compose.runtime.remember for state that should survive recomposition. +- **R-COMPOSE-005** SHOULD: Follow PascalCase naming convention for Composable functions to distinguish from regular functions. +- **R-COMPOSE-006** SHOULD: Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries. + +### Verify + +```bash +# Count @Composable annotations in UI packages +grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Count explicit imports of Composable annotation +grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l + +# Find UI screen files missing @Composable annotation +find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; +``` + +**Accept when:** +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation +- All UI component files contain explicit imports of androidx.compose.runtime.Composable + + +Claude Code MUST NOT skip or defer verification. Build failure occurs if Composable functions violate compiler constraints. Code review rejection is required for UI functions missing @Composable annotation. Automated linting warnings flag missing androidx.compose.runtime.Composable imports. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-combine-get-4258.md b/.actual/rules/cross-cutting-scripts-combine-get-4258.md new file mode 100644 index 00000000000..2877755085a --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-combine-get-4258.md @@ -0,0 +1,36 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Scripts Combine Get + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON responses from external APIs (JIRA, GitHub) and integration test utilities that process configuration files with optional fields. + +### Rules + +- **R-DICT-001** MAY: Scripts MAY combine .get() with explicit None checks when distinguishing between missing keys and null values is required. +- **R-DICT-002** MUST: Use .get() for all external API response field access to prevent KeyError exceptions in CI/CD workflows. +- **R-DICT-003** SHOULD: When accessing nested fields, use .get() with empty dict default for intermediate keys: `response.get('fields', {}).get('field_name')`. +- **R-DICT-004** SHOULD: Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling. +- **R-DICT-005** SHOULD: Add comments documenting why a field might be missing when using .get() for non-obvious cases. +- **R-DICT-006** SHOULD: Consider logging at debug level when .get() returns a default value to aid troubleshooting. +- **R-DICT-007** MUST NOT: Use direct bracket notation for external API response fields unless the API contract explicitly guarantees field presence and KeyError is preferred for contract violations (EXC-001). + +### Verify + +```bash +# Count .get() usage in integration scripts +grep -r '\.get(' .github/scripts/*.py | wc -l + +# Count direct bracket notation (excluding .get() patterns) +grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l + +# Verify scripts compile without syntax errors +python -m py_compile .github/scripts/*.py +``` + +**Accept when:** +- Integration scripts in `.github/scripts/` use .get() for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields +- No syntax errors are detected during compilation + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST execute successfully before accepting changes to integration scripts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-implement-exception-39f9.md b/.actual/rules/cross-cutting-scripts-implement-exception-39f9.md new file mode 100644 index 00000000000..1a16fcac151 --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-implement-exception-39f9.md @@ -0,0 +1,41 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Scripts Implement Exception + +These rules are ALWAYS ACTIVE for all PR automation scripts in the `.github/scripts/` directory, particularly those implementing pattern-based label assignment and GitHub API interactions. + +### Rules + +- **R-EX-001** MUST: Scripts MUST implement exception handling for JSON parsing errors (except json.JSONDecodeError) to gracefully handle malformed configuration files. +- **R-EX-002** MUST: All GitHub API interactions MUST be encapsulated in dedicated functions with `gh_` prefix (e.g., `gh_get_changed_files`, `gh_get_pr_title`, `gh_add_labels`, `gh_replace_labels`). +- **R-EX-003** MUST: Label assignment logic MUST evaluate both `title_patterns` and `path_patterns` from configuration to determine label application. +- **R-EX-004** SHOULD: Configuration-driven pattern matching SHOULD use Python sets for label collection to automatically deduplicate labels before applying to PR. +- **R-EX-005** SHOULD: Key decision points (pattern matches, label additions, API calls) SHOULD include logging statements to enable debugging and audit trail. + +### Verify + +```bash +# Verify JSON configuration loading with exception handling +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions exist +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +# Verify exception handling for JSON parsing +grep -E 'except.*json|JSONDecodeError' .github/scripts/label-pr.py + +# Verify pattern evaluation logic +grep -E '(title_patterns|path_patterns)' .github/scripts/label-pr.py +``` + +**Accept when:** +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json.JSONDecodeError +- All GitHub API interactions are encapsulated in dedicated functions with `gh_` prefix +- The script evaluates both `title_patterns` and `path_patterns` from configuration to determine label assignment +- JSON configuration files are syntactically valid and conform to expected schema +- Python syntax validation passes without errors + + +Claude Code MUST NOT skip or defer verification of these rules. All R-EX rules must be confirmed present in the codebase before accepting PR automation scripts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-provide-appropriate-5bf4.md b/.actual/rules/cross-cutting-scripts-provide-appropriate-5bf4.md new file mode 100644 index 00000000000..ec2786733f0 --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-provide-appropriate-5bf4.md @@ -0,0 +1,31 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Scripts Provide Appropriate + +These rules are ALWAYS ACTIVE for Python scripts in `.github/scripts/` that parse JSON responses from external APIs, integration test utilities that process configuration files with optional fields, and automation scripts that interact with GitHub API, JIRA API, or similar external services. + +### Rules + +- **R-DICT-001** MUST: Scripts MUST provide appropriate default values to .get() when a missing field should result in a specific fallback behavior. + +### Verify + +```bash +# Count .get() usage in scripts +grep -r '\.get(' .github/scripts/*.py | wc -l + +# Count direct bracket notation (should be minimal/justified) +grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l + +# Verify scripts compile without syntax errors +python -m py_compile .github/scripts/*.py +``` + +**Accept when:** +- Integration scripts in `.github/scripts/` use `.get()` for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields +- Nested field access uses pattern: `response.get('fields', {}).get('field_name')` +- Default values are chosen appropriately for business logic (empty string for text, empty list for collections, None when absence needs explicit handling) + + +Claude Code MUST NOT skip or defer verification. All integration scripts accessing external API responses MUST use `.get()` with appropriate defaults. Code review is required for any direct bracket notation on API response fields. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-that-accept-b4a6.md b/.actual/rules/cross-cutting-scripts-that-accept-b4a6.md new file mode 100644 index 00000000000..60b2eff05e3 --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-that-accept-b4a6.md @@ -0,0 +1,38 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Scripts That Accept + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON configuration, accept command-line arguments, or interact with external APIs (GitHub, CI/CD systems). + +### Rules + +- **R-VALIDATE-001** MUST: Scripts that accept command-line arguments MUST use argparse or equivalent structured argument parsing libraries rather than direct sys.argv manipulation. +- **R-VALIDATE-002** MUST: All json.load() calls MUST be wrapped in try-except blocks with specific exception handling for JSONDecodeError to provide clear error messages. +- **R-VALIDATE-003** MUST: Configuration dictionary access MUST use safe access patterns (config.get('key', default_value)) or explicit 'key in dict' checks rather than direct bracket notation (config['key']). +- **R-VALIDATE-004** SHOULD: Scripts that interact with external systems or process untrusted input SHOULD include docstrings or adjacent documentation describing the expected configuration schema. + +### Verify + +```bash +# Check for json.load calls without try-except blocks +grep -r 'json\.load' .github/scripts/ | while read line; do + file=$(echo "$line" | cut -d: -f1) + if ! grep -q "try:" "$file"; then + echo "Missing exception handling: $file" + fi +done + +# Check for unsafe dictionary access (direct bracket notation without .get) +grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' || echo "No unsafe dictionary access detected" + +# Verify argparse usage in scripts accepting arguments +find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l +``` + +**Accept when:** +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries +- Scripts interacting with external systems include documentation of expected configuration schema + + +Claude Code MUST NOT skip or defer verification. All three verification checks MUST pass before accepting changes to scripts in scope. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-that-invoke-3033.md b/.actual/rules/cross-cutting-scripts-that-invoke-3033.md new file mode 100644 index 00000000000..7bb4836deda --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-that-invoke-3033.md @@ -0,0 +1,38 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Scripts That Invoke + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON configuration, invoke external processes via subprocess, or accept command-line arguments. + +### Rules + +- **R-INVOKE-001** SHOULD: Scripts that invoke external processes via subprocess SHOULD sanitize or validate any user-controlled input before passing it to shell commands. +- **R-INVOKE-002** SHOULD: All json.load() calls SHOULD be wrapped in try-except blocks with specific exception handling for JSONDecodeError to provide clear error messages. +- **R-INVOKE-003** SHOULD: Configuration dictionary access SHOULD use safe patterns (.get() methods or explicit 'key in dict' checks) rather than direct bracket notation. +- **R-INVOKE-004** SHOULD: Scripts accepting command-line arguments SHOULD use argparse or equivalent structured parsing libraries with explicit type specifications and help text. + +### Verify + +```bash +# Check for json.load() calls without try-except blocks +grep -r 'json\.load' .github/scripts/ | while read line; do + file=$(echo "$line" | cut -d: -f1) + if ! grep -q "try:" "$file"; then + echo "Missing exception handling: $file" + fi +done + +# Check for unsafe dictionary access (direct bracket notation without .get()) +grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' || echo "No unsafe dictionary access detected" + +# Verify argparse usage in scripts accepting arguments +find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l +``` + +**Accept when:** +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries +- User-controlled input passed to subprocess calls is validated or sanitized before use + + +Claude Code MUST NOT skip or defer verification of these rules. Code review checklist MUST include input validation verification for internal API scripts. Static analysis tools (pylint, bandit) MUST be configured to flag unsafe dictionary access and missing exception handling. CI pipeline MUST include grep-based validation checks for common input validation patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-use-direct-56b5.md b/.actual/rules/cross-cutting-scripts-use-direct-56b5.md new file mode 100644 index 00000000000..0728a49369b --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-use-direct-56b5.md @@ -0,0 +1,35 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Scripts Use Direct + +These rules are ALWAYS ACTIVE for all Python scripts in `.github/scripts/` that parse JSON responses from external APIs (GitHub, JIRA, or similar services) and integration test utilities that process configuration files with optional fields. + +### Rules + +- **R-DICT-001** SHOULD: Scripts SHOULD use `.get()` method for accessing fields from external API responses to safely handle optional or missing fields without raising KeyError exceptions. +- **R-DICT-002** SHOULD: Scripts SHOULD use direct key access (bracket notation) only when the field is guaranteed to exist by API contract or when KeyError is the desired behavior for contract violations. +- **R-DICT-003** SHOULD: When accessing nested fields, use `.get()` with empty dict default for intermediate keys: `response.get('fields', {}).get('field_name')`. +- **R-DICT-004** SHOULD: Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling. +- **R-DICT-005** MAY: Add comments documenting why a field might be missing when using `.get()` for non-obvious cases. +- **R-DICT-006** MAY: Consider logging at debug level when `.get()` returns a default value to aid troubleshooting. + +### Verify + +```bash +# Count .get() usage in scripts +grep -r '\.get(' .github/scripts/*.py | wc -l + +# Count direct bracket notation (excluding .get() patterns) +grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l + +# Verify Python syntax +python -m py_compile .github/scripts/*.py +``` + +**Accept when:** +- Integration scripts in `.github/scripts/` use `.get()` for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields +- No KeyError exceptions are raised during CI/CD workflow execution for missing optional fields + + +Claude Code MUST NOT skip or defer verification. All integration scripts must be reviewed for compliance with R-DICT-001 and R-DICT-002 before merging. Verification commands MUST be executed to confirm no KeyError exceptions occur in production workflows. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-use-predicate-6be1.md b/.actual/rules/cross-cutting-scripts-use-predicate-6be1.md new file mode 100644 index 00000000000..55f29a8f7aa --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-use-predicate-6be1.md @@ -0,0 +1,33 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Scripts Use Predicate + +These rules are ALWAYS ACTIVE for test specification files (*.spec.ts, *.test.ts), automation scripts in .github/scripts/, validation and parsing utilities, and CI/CD pipeline scripts. + +### Rules + +- **R-CORE-001** MAY: Scripts MAY use predicate-based filtering with Array.find() and lambda expressions for locating specific data elements within collections. + +### Verify + +```bash +# Verify vitest usage in TypeScript test specifications +grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l + +# Verify standard library imports for file operations +grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l + +# Verify Python standard library imports only +grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l + +# Verify native collection method usage +grep -r "\.find(\|\.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l +``` + +**Accept when:** +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts +- No prohibited third-party imports (lodash, ramda, etc.) are detected in test or automation script directories + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis MUST check for prohibited third-party imports in test and automation script directories. Code review MUST verify standard library usage for new test specifications and automation scripts. Pull requests adding external dependencies to automation scripts MUST require architecture review and explicit justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-use-standard-13e8.md b/.actual/rules/cross-cutting-scripts-use-standard-13e8.md new file mode 100644 index 00000000000..169f7c11f2c --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-use-standard-13e8.md @@ -0,0 +1,35 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Scripts Use Standard + +These rules are ALWAYS ACTIVE for all Python automation scripts in `.github/scripts/` that implement GitHub integration logic. + +### Rules + +- **R-GITHUB-001** MAY: Scripts MAY use standard library modules (argparse, json, os, subprocess, sys) without introducing external dependencies for GitHub integration. +- **R-GITHUB-002** MUST: Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions. +- **R-GITHUB-003** MUST: Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing. +- **R-GITHUB-004** MUST: Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands. +- **R-GITHUB-005** MUST: Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed. + +### Verify + +```bash +# Verify GitHub integration function naming conventions +grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py + +# Verify JSON parsing includes explicit exception handling +grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py + +# Verify GitHub API interactions use subprocess invocation of gh CLI +grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py +``` + +**Accept when:** +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries +- All subprocess calls capture and log both stdout and stderr with contextual error information +- Label manipulation logic uses Python sets for deduplication before converting to lists for CLI invocation + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for GitHub integration scripts in `.github/scripts/`. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scripts-use-subprocess-0907.md b/.actual/rules/cross-cutting-scripts-use-subprocess-0907.md new file mode 100644 index 00000000000..b3ad1c4ec4d --- /dev/null +++ b/.actual/rules/cross-cutting-scripts-use-subprocess-0907.md @@ -0,0 +1,29 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Scripts Use Subprocess + +These rules are ALWAYS ACTIVE for PR automation scripts in `.github/scripts/` directory, JSON configuration files defining title_patterns and path_patterns, GitHub API wrapper functions, and label assignment logic for application and component classification. + +### Rules + +- **R-SUBPROCESS-001** MAY: Scripts MAY use subprocess module to invoke git or GitHub CLI commands for retrieving PR metadata and file changes. + +### Verify + +```bash +# Verify JSON configuration loading in label-pr.py +grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' + +# Verify GitHub API wrapper functions exist with gh_ prefix +grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py + +# Verify Python syntax is valid +python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' +``` + +**Accept when:** +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST execute successfully before accepting changes to PR automation scripts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-serialization-tests-use-40e0.md b/.actual/rules/cross-cutting-serialization-tests-use-40e0.md new file mode 100644 index 00000000000..570034660a5 --- /dev/null +++ b/.actual/rules/cross-cutting-serialization-tests-use-40e0.md @@ -0,0 +1,39 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Serialization Tests Use + +These rules are ALWAYS ACTIVE for all custom kotlinx.serialization serializers, extension functions converting between domain models and SDK types, and JSON encoding/decoding at service and module boundaries. + +### Rules + +- **R-SER-001** MUST: Serialization tests MUST use buildJsonObject and assertEquals to verify exact JSON output including all properties. +- **R-SER-002** MUST: Tests for versioned schemas MUST validate type discriminator field values in separate test methods for each version. +- **R-SER-003** MUST: Extension function tests (e.g., toSdkPolicyViews) MUST cover edge cases including empty lists and multi-item conversion cases. +- **R-SER-004** MUST: All custom serializers MUST have corresponding test classes with @Test methods. +- **R-SER-005** SHOULD: Mock factory functions (e.g., createMockPolicy) SHOULD be extracted to shared test utilities for reuse across test classes. +- **R-SER-006** SHOULD: JSON comparison SHOULD ignore property order to avoid brittle tests breaking on benign formatting changes. + +### Verify + +```bash +# Count @Test methods in serializer test files +grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l + +# Count buildJsonObject + assertEquals patterns in serialization tests +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l + +# Find test files using kotlinx.serialization +find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +# Verify type discriminator validation in versioned schema tests +grep -r 'discriminator\|v1\|v2' app/src/test/kotlin --include='*Test.kt' | grep -c 'assertEquals' +``` + +**Accept when:** +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases +- Mock factory functions are centralized in shared test utilities + + +Claude Code MUST NOT skip or defer verification. Pull requests adding serializers without tests are blocked in code review. Coverage reports flag untested serialization code for remediation. Architecture review is required for serializers lacking discriminator validation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-serialization-tests-verify-8748.md b/.actual/rules/cross-cutting-serialization-tests-verify-8748.md new file mode 100644 index 00000000000..19197f202a0 --- /dev/null +++ b/.actual/rules/cross-cutting-serialization-tests-verify-8748.md @@ -0,0 +1,40 @@ +# Use JSON Builder DSL for Test Assertion Construction: Serialization Tests Verify + +These rules are ALWAYS ACTIVE for all serialization test files in `app/src/test/kotlin` that verify JSON encoding of domain objects using kotlinx.serialization. + +### Rules + +- **R-SER-001** SHOULD: Serialization tests SHOULD verify type discriminator fields are present in versioned state objects. +- **R-SER-002** MUST: Use buildJsonObject DSL with put operations for constructing expected JSON structures in serialization test assertions. +- **R-SER-003** MUST: Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern. +- **R-SER-004** SHOULD: Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order. +- **R-SER-005** SHOULD: For versioned state objects, verify the type discriminator field first in the buildJsonObject block. +- **R-SER-006** MUST: Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests. +- **R-SER-007** MUST NOT: Use raw JSON strings in assertEquals calls for serialization verification. + +### Verify + +```bash +# Count buildJsonObject usage in test files +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l + +# Verify imports are present +grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' + +# Run serialization and extensions tests +./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' + +# Check for raw JSON strings in test assertions (should return no results) +grep -r 'assertEquals.*"\{' app/src/test/kotlin --include='*Test.kt' +``` + +**Accept when:** +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output +- Type discriminator fields are verified first in buildJsonObject blocks for versioned state objects +- All serialization test files have proper imports for buildJsonObject and put functions + + +Claude Code MUST NOT skip or defer verification of these rules. All serialization tests MUST conform to the buildJsonObject DSL pattern before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-server-implementations-use-4884.md b/.actual/rules/cross-cutting-server-implementations-use-4884.md new file mode 100644 index 00000000000..1a15704fea4 --- /dev/null +++ b/.actual/rules/cross-cutting-server-implementations-use-4884.md @@ -0,0 +1,46 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Server Implementations Use + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, particularly tool execution error handling and fatal error reporting in stdio-based server communication. + +### Rules + +- **R-MCP-001** SHOULD: Server implementations SHOULD use the Server constructor with name, version, and capabilities configuration from @modelcontextprotocol/sdk. +- **R-MCP-002** MUST: Tool execution errors MUST be logged using console.error with the format 'Tool error ({toolName}): {error.message}'. +- **R-MCP-003** MUST: Fatal server errors MUST be logged using console.error with the format 'Fatal error: {error}'. +- **R-MCP-004** MUST: Server implementations MUST use stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr). +- **R-MCP-005** MUST: Tool execution MUST be wrapped in try-catch blocks with appropriate error logging. + +### Verify + +```bash +# Verify Server constructor usage with name, version, and capabilities +grep -r "new Server" .claude/mcp/android-device-server/src/ | grep -E "name|version|capabilities" + +# Verify tool error logging uses correct prefix +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal error logging uses correct prefix +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify @modelcontextprotocol/sdk imports +grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +# Verify stdio transport usage +grep -r "stdio" .claude/mcp/android-device-server/src/ | grep -i transport + +# Verify try-catch blocks around tool execution +grep -r "try" .claude/mcp/android-device-server/src/ | grep -A 5 "catch" +``` + +**Accept when:** +- Server constructor is initialized with name, version, and capabilities configuration +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure +- stdio transport from @modelcontextprotocol/sdk/server/stdio.js is configured +- Tool execution is wrapped in try-catch blocks with error handling +- stderr is reserved for errors while stdout is reserved for protocol messages + + +Claude Code MUST NOT skip or defer verification of these rules. All verification commands MUST pass before accepting MCP server implementations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-server-initialization-declare-ebc9.md b/.actual/rules/cross-cutting-server-initialization-declare-ebc9.md new file mode 100644 index 00000000000..f0d94742404 --- /dev/null +++ b/.actual/rules/cross-cutting-server-initialization-declare-ebc9.md @@ -0,0 +1,40 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Server Initialization Declare + +These rules are ALWAYS ACTIVE for all Android device integration implementations using the Model Context Protocol, specifically for server initialization, tool registration, capability declaration, and stdio-based transport communication. + +### Rules + +- **R-MCP-001** MUST: Server initialization MUST declare capabilities with tools support and include name and version metadata. +- **R-MCP-002** MUST: Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata. +- **R-MCP-003** MUST: Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance. +- **R-MCP-004** MUST: Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing. +- **R-MCP-005** MUST: Implement tool error handling with console.error logging that includes tool name and error message. +- **R-MCP-006** SHOULD: Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity. + +### Verify + +```bash +# Verify SDK server module imports +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . + +# Verify stdio transport imports +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify console.error tool error logging +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capabilities with tools support +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Tool implementations are organized in ./tools/ directory +- Validation utilities are organized in ./utils/ directory + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. Runtime monitoring MUST alert on tool execution failures without proper error logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-server-instances-declare-2d8f.md b/.actual/rules/cross-cutting-server-instances-declare-2d8f.md new file mode 100644 index 00000000000..36da68fc435 --- /dev/null +++ b/.actual/rules/cross-cutting-server-instances-declare-2d8f.md @@ -0,0 +1,29 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Server Instances Declare + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services, including real-time device integration servers, tool-based integration components, bidirectional communication boundaries, and integration points requiring capability negotiation and discovery. + +### Rules + +- **R-MCP-001** MUST: Server instances MUST declare capabilities at initialization time using the capabilities object structure. + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization includes capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic uses collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + + +Verification by static analysis scanning for @modelcontextprotocol/sdk imports in integration server files is mandatory. Code review must verify capabilities declaration in server initialization. Integration tests must verify tool discovery and invocation through MCP protocol. CI pipeline must fail if integration servers lack MCP SDK imports or capabilities declaration. Code review must block merge if tool lookup patterns bypass protocol-standard discovery mechanisms. Architecture review is required for any custom protocol implementation in real-time integration boundaries. Claude Code MUST NOT skip or defer verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-state-classes-implemented-3cf8.md b/.actual/rules/cross-cutting-state-classes-implemented-3cf8.md new file mode 100644 index 00000000000..689c9eec276 --- /dev/null +++ b/.actual/rules/cross-cutting-state-classes-implemented-3cf8.md @@ -0,0 +1,41 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: State Classes Implemented + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the codebase, specifically for UI state management in authentication flows, application-level state coordination, and state objects representing dialog states, loading states, and error states. + +### Rules + +- **R-HILT-001** MUST: State classes MUST be implemented as Parcelable data classes to support state restoration via SavedStateHandle. +- **R-HILT-002** MUST: All ViewModel classes MUST be annotated with @HiltViewModel and use constructor injection for dependencies. +- **R-HILT-003** MUST: State updates MUST use mutableStateFlow.update with copy operations rather than direct value assignment to ensure atomicity. +- **R-HILT-004** MUST: All state properties MUST be immutable (val) within state data classes. +- **R-HILT-005** MUST: Asynchronous operations within ViewModels MUST execute within viewModelScope for proper lifecycle management. +- **R-HILT-006** SHOULD: State SHOULD be exposed to UI as StateFlow using stateIn or asStateFlow to prevent external mutations. +- **R-HILT-007** SHOULD: Complex state variants like dialogs SHOULD use sealed classes for type-safe representation. + +### Verify + +```bash +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management +- State classes define all properties as immutable (val) +- State is exposed to UI as StateFlow to prevent external mutations + + +Clause Code MUST NOT skip or defer verification of these rules during code review and CI pipeline checks. Violations MUST result in build warnings for missing @HiltViewModel annotations, code review rejection for non-compliant state updates, and architecture review requirements for non-Parcelable state classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-state-updates-use-2449.md b/.actual/rules/cross-cutting-state-updates-use-2449.md new file mode 100644 index 00000000000..b31f4796481 --- /dev/null +++ b/.actual/rules/cross-cutting-state-updates-use-2449.md @@ -0,0 +1,33 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: State Updates Use + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the app module that manage UI state across configuration changes and lifecycle events. + +### Rules + +- **R-HILT-001** MUST: State updates MUST use mutableStateFlow.update with copy operations to ensure atomic, thread-safe state transitions. + +### Verify + +```bash +# Count @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages for lifecycle management +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + + +Claude Code MUST NOT skip or defer verification. All state update patterns in ViewModels must conform to the mutableStateFlow.update pattern with copy operations. Code review rejection is required for violations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-stdio-transport-imported-10ae.md b/.actual/rules/cross-cutting-stdio-transport-imported-10ae.md new file mode 100644 index 00000000000..d4b9b46a60a --- /dev/null +++ b/.actual/rules/cross-cutting-stdio-transport-imported-10ae.md @@ -0,0 +1,37 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Stdio Transport Imported + +These rules are ALWAYS ACTIVE for all Android device MCP server implementations using the Model Context Protocol SDK for stdio-based transport communication. + +### Rules + +- **R-MCP-001** MUST: Stdio transport MUST be imported from @modelcontextprotocol/sdk/server/stdio.js for communication channel establishment +- **R-MCP-002** MUST: Server construction MUST be imported from @modelcontextprotocol/sdk/server/index.js and initialized with name 'android-device-mcp' and version metadata +- **R-MCP-003** MUST: Type definitions MUST be imported from @modelcontextprotocol/sdk/types.js for request/response message typing +- **R-MCP-004** MUST: Tool error handling MUST use console.error logging that includes tool name and error message +- **R-MCP-005** MUST: Server initialization MUST include capability declarations with tools support +- **R-MCP-006** SHOULD: Tool implementations SHOULD be organized in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +### Verify + +```bash +# Verify SDK imports are present +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify error handling patterns +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capability declarations +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Tool implementations are organized in ./tools/ directory and validation utilities in ./utils/ directory + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. Runtime monitoring MUST alert on tool execution failures without proper error logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-assertions-verifying-cd9f.md b/.actual/rules/cross-cutting-test-assertions-verifying-cd9f.md new file mode 100644 index 00000000000..6a78b620059 --- /dev/null +++ b/.actual/rules/cross-cutting-test-assertions-verifying-cd9f.md @@ -0,0 +1,31 @@ +# Use JSON Builder DSL for Test Assertion Construction: Test Assertions Verifying + +These rules are ALWAYS ACTIVE for all test files that verify JSON serialization output using kotlinx.serialization. + +### Rules + +- **R-TEST-ASSERT-001** MUST: Test assertions verifying JSON serialization output MUST use buildJsonObject DSL to construct expected JSON structures. + +### Verify + +```bash +# Count buildJsonObject usage in test files +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l + +# Verify imports are present +grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' + +# Run serialization and extensions tests +./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' +``` + +**Accept when:** +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output +- Type discriminator fields are verified first in buildJsonObject blocks for versioned state objects +- One put call per line is used for readability in buildJsonObject blocks + + +Claude Code MUST NOT skip or defer verification of buildJsonObject DSL usage in serialization tests. Code review and CI pipeline validation are mandatory before accepting changes to test assertion patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-classes-follow-9b1c.md b/.actual/rules/cross-cutting-test-classes-follow-9b1c.md new file mode 100644 index 00000000000..29bbd5b1610 --- /dev/null +++ b/.actual/rules/cross-cutting-test-classes-follow-9b1c.md @@ -0,0 +1,38 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Test Classes Follow + +These rules are ALWAYS ACTIVE for all custom kotlinx.serialization serializers, extension functions converting between domain models and SDK types, and JSON encoding/decoding at service and module boundaries. + +### Rules + +- **R-SERIAL-001** SHOULD: Test classes SHOULD follow naming convention `Test` for serializers and extension functions. +- **R-SERIAL-002** SHOULD: Serialization tests SHOULD use `buildJsonObject` and `assertEquals` to verify exact JSON structure including discriminator fields and property mappings. +- **R-SERIAL-003** SHOULD: Tests for versioned schemas SHOULD validate type discriminator field values (e.g., 'v1', 'v2') in separate test methods for each version. +- **R-SERIAL-004** SHOULD: Extension function tests SHOULD cover edge cases such as empty lists and multi-item collections. +- **R-SERIAL-005** SHOULD: Mock factory functions (e.g., `createMockPolicy`) SHOULD be extracted to shared test utilities for reuse across test classes. + +### Verify + +```bash +# Count @Test annotations in serializer test files +grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l + +# Count buildJsonObject with assertEquals patterns in test files +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l + +# Find serializer and extension test files using kotlinx.serialization +find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +# Verify test class naming convention matches Test pattern +find app/src/test/kotlin -name '*Test.kt' | xargs grep -l 'buildJsonObject' | xargs basename -a | grep -E '^[A-Z][a-zA-Z0-9]*Test\.kt$' +``` + +**Accept when:** +- All custom serializers have corresponding test classes with `@Test` methods following `Test` naming convention +- Serialization tests use `buildJsonObject` and `assertEquals` to verify JSON structure +- Tests for versioned schemas validate type discriminator field values in separate test methods +- Extension function tests cover empty input and multi-item conversion cases +- Mock factory functions are extracted to shared test utilities and reused across test classes + + +Claude Code MUST NOT skip or defer verification of these serialization testing standards. All custom serializers and extension functions crossing service boundaries MUST have corresponding test classes validating JSON contracts and type discriminators. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-classes-implement-2b73.md b/.actual/rules/cross-cutting-test-classes-implement-2b73.md new file mode 100644 index 00000000000..0e5f76406d5 --- /dev/null +++ b/.actual/rules/cross-cutting-test-classes-implement-2b73.md @@ -0,0 +1,42 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Classes Implement + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that validate JSON structure, configuration, or CI/CD artifacts, and for integration tests that validate public API contracts of utility functions. + +### Rules + +- **R-TEST-001** MUST: Test classes MUST implement `setUp` method to initialize test fixtures, file paths, and resource state before each test execution. +- **R-TEST-002** MUST: Test classes that use fixtures MUST implement `tearDown` method to clean up resources and restore state after each test execution. +- **R-TEST-003** MUST: Test methods MUST follow the `test_*` naming convention and include docstrings that explain what contract or behavior is being validated. +- **R-TEST-004** MUST: Test classes MUST inherit from `unittest.TestCase`. +- **R-TEST-005** SHOULD: Store test fixtures in a `fixtures/` subdirectory adjacent to test files, using descriptive names (e.g., `sample-valid1.json`, `sample-invalid.json`). +- **R-TEST-006** SHOULD: Construct fixture paths using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-TEST-007** SHOULD: Use `try/finally` blocks or context managers in `tearDown` to ensure cleanup runs even if tests fail. +- **R-TEST-008** MAY: Use `patch('sys.stdout', new=io.StringIO())` in `setUp` and stop in `tearDown` to suppress output from CLI utilities during testing. + +### Verify + +```bash +# Verify all test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp methods are implemented +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown methods are implemented +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run all tests via unittest discovery +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via unittest discovery +- Fixture paths are constructed using `os.path.dirname(__file__)` for portability +- Resource cleanup is guaranteed through `try/finally` or context managers in `tearDown` + + +Claude Code MUST NOT skip or defer verification. All test files in `.github/scripts/` MUST be checked for compliance with R-TEST-001 through R-TEST-008. CI pipeline MUST run unittest discovery and verify test structure before accepting changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-classes-implement-772c.md b/.actual/rules/cross-cutting-test-classes-implement-772c.md new file mode 100644 index 00000000000..7b8c77e63ad --- /dev/null +++ b/.actual/rules/cross-cutting-test-classes-implement-772c.md @@ -0,0 +1,31 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Test Classes Implement + +These rules are ALWAYS ACTIVE for all Python test modules in `.github/scripts/*/test_*.py` and all TypeScript test modules in `.claude/mcp/**/src/**/*.spec.ts`. + +### Rules + +- **R-TEST-001** SHOULD: Test classes SHOULD implement setUp and tearDown methods for test fixture initialization and cleanup. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase with setUp/tearDown +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests use vitest with describe/it structure +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files to ensure coverage +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class and `test_*` method naming convention +- All TypeScript test files use vitest with `describe`/`it` structure and `*.spec.ts` naming convention +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- Python tests implement `setUp` and `tearDown` methods for fixture management +- TypeScript tests implement `beforeEach` and `afterEach` hooks for fixture management + + +Claude Code MUST NOT skip or defer verification. All test files must conform to the specified frameworks and lifecycle patterns before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-classes-implement-dead.md b/.actual/rules/cross-cutting-test-classes-implement-dead.md new file mode 100644 index 00000000000..fd6b36a6b30 --- /dev/null +++ b/.actual/rules/cross-cutting-test-classes-implement-dead.md @@ -0,0 +1,39 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Classes Implement + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that use `unittest.TestCase` and manage test fixtures or resources. + +### Rules + +- **R-TEST-001** MUST: Test classes MUST implement `tearDown` method to clean up resources, restore state, and prevent test pollution. +- **R-TEST-002** MUST: All test classes in `.github/scripts/` MUST inherit from `unittest.TestCase`. +- **R-TEST-003** MUST: Test methods MUST follow the `test_*` naming convention and include docstrings explaining the contract being validated. +- **R-TEST-004** SHOULD: Construct fixture paths using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-TEST-005** SHOULD: Store test fixtures in a `fixtures/` subdirectory adjacent to test files, using descriptive names. +- **R-TEST-006** MAY: Use `patch('sys.stdout', new=io.StringIO())` in `setUp` and stop in `tearDown` to suppress output from CLI utilities during testing. + +### Verify + +```bash +# Verify unittest.TestCase inheritance +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp implementation +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown implementation +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run all tests via unittest discovery +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via unittest discovery +- Fixture paths use `os.path.join(os.path.dirname(__file__), ...)` for portability + + +Claude Code MUST NOT skip or defer verification. All test classes using fixtures MUST implement tearDown. CI pipeline MUST run unittest discovery on all test_*.py files in .github/scripts/ and fail the build if tests do not follow the unittest.TestCase pattern or if tearDown is missing from fixture-using test classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-classes-inherit-bf00.md b/.actual/rules/cross-cutting-test-classes-inherit-bf00.md new file mode 100644 index 00000000000..90e235081f1 --- /dev/null +++ b/.actual/rules/cross-cutting-test-classes-inherit-bf00.md @@ -0,0 +1,41 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Classes Inherit + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that validate JSON structure, configuration, or CI/CD artifacts, and for integration tests that validate public API contracts of utility functions. + +### Rules + +- **R-TEST-001** MUST: All test classes MUST inherit from `unittest.TestCase` to provide standardized test discovery and execution. +- **R-TEST-002** MUST: Test classes that use fixtures MUST implement both `setUp` and `tearDown` methods for consistent lifecycle management. +- **R-TEST-003** MUST: Test methods MUST follow the `test_*` naming convention and include docstrings that explain what contract or behavior is being validated. +- **R-TEST-004** SHOULD: Store test fixtures in a `fixtures/` subdirectory adjacent to test files, using descriptive names (e.g., `sample-valid1.json`, `sample-invalid.json`). +- **R-TEST-005** SHOULD: Construct fixture paths using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-TEST-006** SHOULD: Use `try/finally` blocks or context managers in `tearDown` to ensure cleanup runs even if tests fail. +- **R-TEST-007** MAY: Use `setUpClass`/`tearDownClass` for expensive fixtures that can be safely shared across all test methods without pollution risk. + +### Verify + +```bash +# Verify all test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp methods are implemented +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown methods are implemented +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run unittest discovery to verify all tests pass +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via `unittest discover` +- Fixture paths are constructed using `os.path.join(os.path.dirname(__file__), ...)` +- `tearDown` methods use `try/finally` or context managers to guarantee cleanup + + +Claude Code MUST NOT skip or defer verification. All test files in `.github/scripts/` MUST be checked for `unittest.TestCase` inheritance, `setUp`/`tearDown` implementation, and successful test discovery execution before accepting changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-classes-organize-d158.md b/.actual/rules/cross-cutting-test-classes-organize-d158.md new file mode 100644 index 00000000000..0deb2ceaef3 --- /dev/null +++ b/.actual/rules/cross-cutting-test-classes-organize-d158.md @@ -0,0 +1,29 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Test Classes Organize + +These rules are ALWAYS ACTIVE for all network layer unit tests in `network/src/test/kotlin/**/*Test.kt` that validate HTTP error response handling, exception transformations, and error parsing logic. + +### Rules + +- **R-TEST-001** MAY: Test classes MAY organize error handling tests by exception type (e.g., BitwardenErrorTest, ExceptionExtensionsTest) for clarity. + +### Verify + +```bash +# Count Response.error() usage in test files +grep -r "Response.error" network/src/test/kotlin/ | wc -l + +# Count @Test methods for exception/error handling +grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l + +# Count assertion usage in error handling tests +grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l +``` + +**Accept when:** +- At least 2 test files use `Response.error()` with `toResponseBody()` for HTTP error mocking +- All custom exception types have corresponding `@Test` methods validating `toBitwardenError()` transformations +- Error parsing tests include `assertEquals` assertions for both `message` and `validationErrors` fields + + +Clause Code MUST NOT skip or defer verification. All error handling tests MUST follow the organized structure by exception type and use OkHttp mock responses with JUnit 5 assertions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-descriptions-use-18ee.md b/.actual/rules/cross-cutting-test-descriptions-use-18ee.md new file mode 100644 index 00000000000..55683de028e --- /dev/null +++ b/.actual/rules/cross-cutting-test-descriptions-use-18ee.md @@ -0,0 +1,30 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Test Descriptions Use + +These rules are ALWAYS ACTIVE for all Python test modules in `.github/scripts/*/test_*.py` and all TypeScript test modules in `.claude/mcp/**/src/**/*.spec.ts`. + +### Rules + +- **R-TEST-001** SHOULD: Test descriptions SHOULD use docstrings (Python) or string literals (TypeScript) to document test intent. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase with docstrings +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests import from vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files to ensure coverage +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class with `test_*` method naming convention and include docstrings documenting test intent +- All TypeScript test files use vitest with `describe/it` structure, `*.spec.ts` naming convention, and include string literals documenting test intent +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- All test methods and test cases include descriptive documentation of their purpose + + +Claude Code MUST NOT skip or defer verification. All test files must conform to the documented framework patterns and include descriptive test documentation before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-fixtures-organized-85db.md b/.actual/rules/cross-cutting-test-fixtures-organized-85db.md new file mode 100644 index 00000000000..2e89a3cb770 --- /dev/null +++ b/.actual/rules/cross-cutting-test-fixtures-organized-85db.md @@ -0,0 +1,42 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Test Fixtures Organized + +These rules are ALWAYS ACTIVE for all Python test modules in `.github/scripts/*/test_*.py` and all TypeScript test modules in `.claude/mcp/**/src/**/*.spec.ts`. + +### Rules + +- **R-TEST-001** SHOULD: Test fixtures SHOULD be organized in dedicated `fixtures/` directories relative to test files. +- **R-TEST-002** MUST: All Python test files MUST use `unittest.TestCase` base class with test methods prefixed by `test_`. +- **R-TEST-003** MUST: All TypeScript test files MUST use vitest with `describe`/`it` structure and `*.spec.ts` naming convention. +- **R-TEST-004** SHOULD: Test lifecycle management SHOULD use `setUp`/`tearDown` (Python) or `beforeEach`/`afterEach` (TypeScript) for resource initialization and cleanup. +- **R-TEST-005** SHOULD: Test fixtures SHOULD be loaded using `os.path.join` (Python) or `node:path` (TypeScript) for proper path resolution. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests use vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +# Verify test file naming conventions +find .github/scripts -name 'test_*.py' | wc -l +find .claude/mcp -name '*.spec.ts' | wc -l + +# Verify fixtures directories exist +find . -path '*/fixtures/*' -type f | head -20 +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class and `test_*` method naming convention +- All TypeScript test files use vitest with `describe`/`it` structure and `*.spec.ts` naming convention +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- Test lifecycle methods (`setUp`/`tearDown` or `beforeEach`/`afterEach`) are present for resource management +- No test files use non-standard frameworks (pytest, Jest, or other alternatives) without documented exception + + +Claude Code MUST NOT skip or defer verification of test framework compliance and fixture organization. All pull requests introducing test files MUST conform to these rules or include documented architectural exception approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-fixtures-use-0e93.md b/.actual/rules/cross-cutting-test-fixtures-use-0e93.md new file mode 100644 index 00000000000..dbeb4eec43a --- /dev/null +++ b/.actual/rules/cross-cutting-test-fixtures-use-0e93.md @@ -0,0 +1,42 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Fixtures Use + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that validate JSON structure, configuration, or CI/CD artifacts, and for integration tests that validate public API contracts of utility functions. + +### Rules + +- **R-TEST-001** MUST: Test classes in `.github/scripts/` MUST inherit from `unittest.TestCase`. +- **R-TEST-002** MUST: Test classes that use fixtures MUST implement both `setUp` and `tearDown` methods. +- **R-TEST-003** MUST: Test methods MUST follow the `test_*` naming convention. +- **R-TEST-004** SHOULD: Test fixtures SHOULD use file-based resources stored in a `fixtures/` subdirectory relative to the test file. +- **R-TEST-005** SHOULD: Fixture paths SHOULD be constructed using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-TEST-006** SHOULD: Test methods SHOULD include docstrings that explain what contract or behavior is being validated. +- **R-TEST-007** SHOULD: Fixture files SHOULD use descriptive names like `sample-valid1.json`, `sample-invalid.json`. +- **R-TEST-008** MAY: Use `patch('sys.stdout', new=io.StringIO())` in `setUp` and stop in `tearDown` to suppress output from CLI utilities during testing. + +### Verify + +```bash +# Verify all test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp methods exist in test classes +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown methods exist in test classes +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run unittest discovery to verify all tests pass +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via `unittest discover -s .github/scripts/ -p 'test_*.py'` +- Fixture files are stored in `fixtures/` subdirectories adjacent to test files +- Fixture paths are constructed using `os.path.dirname(__file__)` for portability + + +Claude Code MUST NOT skip or defer verification. All test files in `.github/scripts/` MUST be checked for compliance with R-TEST-001 through R-TEST-008. CI pipeline MUST run unittest discovery and fail the build if tests do not follow the unittest.TestCase pattern. Code review MUST verify setUp/tearDown implementation for new test classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-method-names-f006.md b/.actual/rules/cross-cutting-test-method-names-f006.md new file mode 100644 index 00000000000..cbc3358d2cd --- /dev/null +++ b/.actual/rules/cross-cutting-test-method-names-f006.md @@ -0,0 +1,33 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Test Method Names + +These rules are ALWAYS ACTIVE for all Python test files with `test_` prefix or `_test` suffix, and all TypeScript test files with `.spec.ts` or `.test.ts` extensions, including unit tests, integration tests, and functional tests in both languages. + +### Rules + +- **R-TEST-001** SHOULD: Test method names SHOULD follow descriptive naming conventions that clearly indicate the behavior being tested (e.g., `test_validate_json_valid`, `test_find_duplicates_returns_empty_list_when_no_duplicates`). + +### Verify + +```bash +# Verify Python test files use unittest framework +grep -r 'import unittest' --include='test_*.py' .github/scripts/ + +# Verify TypeScript test files use vitest framework +grep -r 'from vitest import' --include='*.spec.ts' .claude/ + +# Verify Python test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' --include='test_*.py' . + +# Verify TypeScript test files use describe/it structure +grep -r 'describe\|it' --include='*.spec.ts' . +``` + +**Accept when:** +- All Python test files contain `import unittest` and define classes inheriting from `unittest.TestCase` +- All TypeScript test files with `.spec.ts` extension import from `vitest` and use `describe`/`it` structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results +- Test method names follow descriptive naming conventions indicating the behavior being tested + + +Claude Code MUST NOT skip or defer verification. CI pipeline test execution requires unittest and vitest as test runners. Code review must verify test framework compliance for new test files. Static analysis linting rules must detect non-compliant test patterns. Violations result in CI build failure or code review block unless documented exception is approved by engineering lead or architecture review board. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-methods-include-02ab.md b/.actual/rules/cross-cutting-test-methods-include-02ab.md new file mode 100644 index 00000000000..994987e63ac --- /dev/null +++ b/.actual/rules/cross-cutting-test-methods-include-02ab.md @@ -0,0 +1,41 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Methods Include + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that use `unittest.TestCase` and manage test fixtures through setUp/tearDown lifecycle methods. + +### Rules + +- **R-TEST-001** MUST: Test classes in `.github/scripts/` that manage fixtures MUST implement both `setUp` and `tearDown` methods for consistent test isolation and resource cleanup. +- **R-TEST-002** MUST: Test methods MUST follow the `test_*` naming convention to enable unittest discovery and execution. +- **R-TEST-003** SHOULD: Test methods SHOULD include docstrings that clearly describe the contract being tested. +- **R-TEST-004** SHOULD: Fixture paths SHOULD be constructed using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-TEST-005** SHOULD: Test fixtures SHOULD be stored in a `fixtures/` subdirectory adjacent to test files, using descriptive names (e.g., `sample-valid1.json`, `sample-invalid.json`). +- **R-TEST-006** SHOULD: Output suppression in setUp/tearDown SHOULD use `patch('sys.stdout', new=io.StringIO())` to suppress CLI utility output during testing. +- **R-TEST-007** SHOULD: tearDown implementations SHOULD use try/finally blocks or context managers to ensure cleanup runs even if tests fail. + +### Verify + +```bash +# Verify unittest.TestCase inheritance +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp implementation +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown implementation +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run unittest discovery +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via unittest discovery +- Fixture paths use `os.path.join(os.path.dirname(__file__), ...)` for portability +- Test fixtures are stored in descriptive `fixtures/` subdirectories + + +Claude Code MUST NOT skip or defer verification. All test files in `.github/scripts/` must be checked for compliance with R-TEST-001 through R-TEST-007 before accepting changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-methods-use-27a4.md b/.actual/rules/cross-cutting-test-methods-use-27a4.md new file mode 100644 index 00000000000..6be58109101 --- /dev/null +++ b/.actual/rules/cross-cutting-test-methods-use-27a4.md @@ -0,0 +1,30 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Test Methods Use + +These rules are ALWAYS ACTIVE for all network layer unit tests in `network/src/test/kotlin/**/*Test.kt`, particularly those validating `toBitwardenError()` extension functions, `parseErrorBodyOrNull()` error parsing logic, and HTTP error response mocking for status codes 400-599. + +### Rules + +- **R-HTTP-TEST-001** SHOULD: Test methods SHOULD use `assertTrue` for type checking error instances before casting to specific error types. + +### Verify + +```bash +# Count Response.error() usage in test files +grep -r "Response.error" network/src/test/kotlin/ | wc -l + +# Count @Test methods validating BitwardenError or Exception transformations +grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l + +# Count assertEquals and assertTrue assertions in error-related tests +grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l +``` + +**Accept when:** +- At least 2 test files use `Response.error()` with `toResponseBody()` for HTTP error mocking +- All custom exception types (CookieRedirectException, LocalNetworkAccessException) have corresponding `@Test` methods validating `toBitwardenError()` transformations +- Error parsing tests include `assertEquals` assertions for both `message` and `validationErrors` fields +- `assertTrue` is used to type-check error instances before casting in error transformation tests + + +Claude Code MUST NOT skip or defer verification of these rules during code review or test implementation. All new error types added to the network layer MUST include corresponding unit tests following this pattern, or pull requests MUST be blocked until tests are added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-methods-verifying-597c.md b/.actual/rules/cross-cutting-test-methods-verifying-597c.md new file mode 100644 index 00000000000..ba5c866df04 --- /dev/null +++ b/.actual/rules/cross-cutting-test-methods-verifying-597c.md @@ -0,0 +1,30 @@ +# Use JSON Builder DSL for Test Assertion Construction: Test Methods Verifying + +These rules are ALWAYS ACTIVE for all test files verifying JSON serialization using kotlinx.serialization. + +### Rules + +- **R-JSON-001** SHOULD: Test methods verifying serialization SHOULD use assertEquals to compare buildJsonObject output with json.encodeToJsonElement results. + +### Verify + +```bash +# Count buildJsonObject usage in test files +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l + +# Verify imports are present +grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' + +# Run serialization and extensions tests +./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' +``` + +**Accept when:** +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output +- Type discriminator fields are verified first in buildJsonObject blocks for versioned state objects + + +Claude Code MUST NOT skip or defer verification of this rule during test method review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-specifications-typescript-ff88.md b/.actual/rules/cross-cutting-test-specifications-typescript-ff88.md new file mode 100644 index 00000000000..6de0e95620b --- /dev/null +++ b/.actual/rules/cross-cutting-test-specifications-typescript-ff88.md @@ -0,0 +1,43 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Test Specifications Typescript + +These rules are ALWAYS ACTIVE for all TypeScript test specifications (*.spec.ts, *.test.ts), Python automation scripts in .github/scripts/, validation and parsing utilities, and CI/CD pipeline scripts. + +### Rules + +- **R-CORE-001** MUST: Test specifications in TypeScript MUST use vitest as the test framework with standard describe/it block structure for organizing test cases. +- **R-CORE-002** MUST: Test and automation scripts MUST use only standard library modules (node:fs, node:path for TypeScript; json, sys, os, argparse for Python) for core functionality without external collection libraries (lodash, ramda, underscore). +- **R-CORE-003** MUST: Data access patterns MUST consistently use native collection methods (Array.find(), Set.add() in TypeScript; json.load() in Python) rather than abstraction layers or third-party query libraries. +- **R-CORE-004** SHOULD: Shared utility modules SHOULD be created for common data access patterns (parseJsonFile(), findInCollection(), addToSet()) to reduce duplication while maintaining standard library usage. +- **R-CORE-005** SHOULD: New automation scripts SHOULD use existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) as templates to ensure consistency in import patterns and data access approaches. +- **R-CORE-006** MAY: External API contracts MAY require specific JSON schema validation libraries beyond standard json module capabilities (EXC-002). +- **R-CORE-007** MAY: Performance profiling MAY indicate native collection methods create bottlenecks in large dataset processing, triggering refactor to query libraries (EXC-001). + +### Verify + +```bash +# Verify vitest usage in TypeScript test specifications +grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l + +# Verify standard library file operations +grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l + +# Verify Python standard library imports +grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l + +# Verify native collection method usage +grep -r "\.find(\|\.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +# Flag prohibited third-party imports in test/automation directories +grep -r "import.*lodash\|import.*ramda\|import.*underscore" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py +``` + +**Accept when:** +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts +- No prohibited third-party imports (lodash, ramda, underscore) are detected in test or automation script directories +- Shared utility modules exist for common patterns without introducing external dependencies + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis MUST check for prohibited third-party imports in test and automation script directories. Code review MUST verify standard library usage for new test specifications and automation scripts. Pull requests adding external dependencies to automation scripts MUST require architecture review and explicit justification. Violations trigger CI build failure and technical debt tracking. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-suppress-stdout-270e.md b/.actual/rules/cross-cutting-tests-suppress-stdout-270e.md new file mode 100644 index 00000000000..784a10769b6 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-suppress-stdout-270e.md @@ -0,0 +1,41 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Tests Suppress Stdout + +These rules are ALWAYS ACTIVE for all Python test files in `.github/scripts/` that validate JSON structure, configuration, or CI/CD artifacts using unittest.TestCase with fixture initialization and resource cleanup. + +### Rules + +- **R-TEST-001** MUST: All test classes in `.github/scripts/` inherit from `unittest.TestCase`. +- **R-TEST-002** MUST: Test classes that use fixtures implement both `setUp` and `tearDown` methods. +- **R-TEST-003** MUST: Test methods follow the `test_*` naming convention and include docstrings explaining the contract being validated. +- **R-TEST-004** SHOULD: Store test fixtures in a `fixtures/` subdirectory adjacent to test files, using descriptive names (e.g., `sample-valid1.json`, `sample-invalid.json`). +- **R-TEST-005** SHOULD: Construct fixture paths using `os.path.join(os.path.dirname(__file__), 'fixtures/filename')` to ensure portability across execution environments. +- **R-TEST-006** MAY: Tests MAY suppress stdout/stderr using patches or context managers (e.g., `patch('sys.stdout', new=io.StringIO())`) when testing CLI utilities to reduce noise. +- **R-TEST-007** SHOULD: Use try/finally blocks or context managers in `tearDown` to ensure cleanup runs even if tests fail. + +### Verify + +```bash +# Verify unittest.TestCase inheritance +grep -r 'class.*unittest\.TestCase' .github/scripts/ + +# Verify setUp implementation +grep -r 'def setUp\(self\):' .github/scripts/ + +# Verify tearDown implementation +grep -r 'def tearDown\(self\):' .github/scripts/ + +# Run all tests via unittest discovery +python -m unittest discover -s .github/scripts/ -p 'test_*.py' +``` + +**Accept when:** +- All test classes in `.github/scripts/` inherit from `unittest.TestCase` +- Test classes that use fixtures implement both `setUp` and `tearDown` methods +- Test methods follow `test_*` naming convention and include docstrings +- All tests pass when executed via unittest discovery +- Fixture paths use `os.path.join(os.path.dirname(__file__), ...)` for portability +- stdout/stderr suppression uses patches or context managers where appropriate + + +Claude Code MUST NOT skip or defer verification. All test files in `.github/scripts/` MUST be validated against these rules before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-buildjsonobject-c361.md b/.actual/rules/cross-cutting-tests-use-buildjsonobject-c361.md new file mode 100644 index 00000000000..6276eb2f1d6 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-buildjsonobject-c361.md @@ -0,0 +1,35 @@ +# Use JSON Builder DSL for Test Assertion Construction: Tests Use Buildjsonobject + +These rules are ALWAYS ACTIVE for all test files in `app/src/test/kotlin/` that verify JSON serialization behavior using kotlinx.serialization. + +### Rules + +- **R-TEST-JSON-001** MAY: Tests MAY use buildJsonObject for constructing complex nested JSON structures when testing deep object hierarchies. +- **R-TEST-JSON-002** SHOULD: Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern. +- **R-TEST-JSON-003** SHOULD: Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order. +- **R-TEST-JSON-004** SHOULD: For versioned state objects, always verify the type discriminator field first in the buildJsonObject block. +- **R-TEST-JSON-005** SHOULD: Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests. + +### Verify + +```bash +# Count buildJsonObject usage in test files +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l + +# Verify imports are present +grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' + +# Run serialization and extensions tests +./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' +``` + +**Accept when:** +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output +- Type discriminator fields are verified first in versioned state object tests +- buildJsonObject blocks follow consistent formatting with one put call per line + + +Clause Code MUST NOT skip or defer verification of these rules during test file review. Serialization tests MUST use buildJsonObject DSL for JSON structure assertions. Violations MUST be flagged in code review with examples of correct pattern usage. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-mock-0deb.md b/.actual/rules/cross-cutting-tests-use-mock-0deb.md new file mode 100644 index 00000000000..2e4162aebad --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-mock-0deb.md @@ -0,0 +1,44 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Tests Use Mock + +These rules are ALWAYS ACTIVE for all custom kotlinx.serialization serializers, extension functions converting between domain models and SDK types, and JSON encoding/decoding at service and module boundaries. + +### Rules + +- **R-SER-001** MAY: Tests MAY use mock factory functions (e.g., createMockPolicy) to generate test data consistently. +- **R-SER-002** MUST: All custom serializers have corresponding test classes with @Test methods. +- **R-SER-003** MUST: Serialization tests use buildJsonObject and assertEquals to verify exact JSON structure. +- **R-SER-004** MUST: Tests for versioned schemas validate type discriminator field values. +- **R-SER-005** MUST: Extension function tests cover empty input and multi-item conversion cases. +- **R-SER-006** SHOULD: Use JSON comparison that ignores property order to avoid brittle tests on benign formatting changes. +- **R-SER-007** SHOULD: Extract mock factory functions to shared test utilities for reuse across test classes. + +### Verify + +```bash +# Count serializer test classes +grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l + +# Count buildJsonObject with assertEquals patterns +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l + +# Find serialization test files using kotlinx.serialization +find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +# Verify type discriminator validation in versioned schema tests +grep -r 'type.*discriminator\|discriminator.*field' app/src/test/kotlin --include='*Test.kt' + +# Check for edge case coverage in extension function tests +grep -r 'emptyList\|empty.*input\|multi.*item' app/src/test/kotlin --include='*ExtensionsTest.kt' +``` + +**Accept when:** +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases +- Mock factory functions are extracted to shared test utilities for reuse +- Test coverage reporting shows serialization packages are adequately tested + + +Claude Code MUST NOT skip or defer verification. All custom serializers crossing service boundaries MUST have corresponding unit tests validating exact JSON structure including type discriminators. Pull requests adding serializers without tests MUST be blocked in code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-mocking-4a66.md b/.actual/rules/cross-cutting-tests-use-mocking-4a66.md new file mode 100644 index 00000000000..b6a332e72a5 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-mocking-4a66.md @@ -0,0 +1,37 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Tests Use Mocking + +These rules are ALWAYS ACTIVE for all Python test files with `test_` prefix or `_test` suffix, and all TypeScript test files with `.spec.ts` or `.test.ts` extensions. + +### Rules + +- **R-TEST-001** MAY: Tests MAY use mocking and patching utilities provided by the respective framework ecosystem (unittest.mock for Python, vitest mocking for TypeScript). +- **R-TEST-002** MUST: All Python test files shall import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with `test_`. +- **R-TEST-003** MUST: All TypeScript test files shall import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping. +- **R-TEST-004** SHOULD: Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management. +- **R-TEST-005** SHOULD: Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks. + +### Verify + +```bash +# Verify Python test files use unittest +grep -r 'import unittest' --include='test_*.py' .github/scripts/ + +# Verify TypeScript test files use vitest +grep -r 'from vitest import' --include='*.spec.ts' .claude/ + +# Verify Python test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' --include='test_*.py' . + +# Verify TypeScript tests use describe/it structure +grep -r 'describe\|it' --include='*.spec.ts' . +``` + +**Accept when:** +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results +- No plain assert statements are used in unittest.TestCase classes (use unittest assertion methods instead) + + +Claude Code MUST NOT skip or defer verification. All test files must comply with the specified framework requirements before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verify-both-6b75.md b/.actual/rules/cross-cutting-tests-verify-both-6b75.md new file mode 100644 index 00000000000..12a7d9530c4 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verify-both-6b75.md @@ -0,0 +1,45 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Tests Verify Both + +These rules are ALWAYS ACTIVE for all Python test modules in `.github/scripts/*/test_*.py` and all TypeScript test modules in `.claude/mcp/**/src/**/*.spec.ts`. + +### Rules + +- **R-TEST-001** MUST: Tests MUST verify both positive cases (valid inputs) and negative cases (invalid inputs). +- **R-TEST-002** MUST: All Python test files MUST use `unittest.TestCase` base class with test methods prefixed by `test_`. +- **R-TEST-003** MUST: All TypeScript test files MUST use vitest with `describe`/`it` structure and `*.spec.ts` naming convention. +- **R-TEST-004** MUST: Test fixtures MUST be organized in dedicated `fixtures/` directories relative to test files. +- **R-TEST-005** MUST: Python tests MUST use `setUp`/`tearDown` lifecycle methods for resource initialization and cleanup. +- **R-TEST-006** MUST: TypeScript tests MUST use `beforeEach`/`afterEach` for test lifecycle management. +- **R-TEST-007** SHOULD: Test fixtures SHOULD be loaded using `os.path.join` (Python) or `node:path` (TypeScript) for proper path resolution. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests import from vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files to ensure coverage +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +# Verify test file naming conventions +find .github/scripts -name 'test_*.py' | wc -l +find .claude/mcp -name '*.spec.ts' | wc -l + +# Verify fixtures directory structure exists +find . -type d -name 'fixtures' | grep -E '(test_|spec)' +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class and `test_*` method naming convention +- All TypeScript test files use vitest with `describe`/`it` structure and `*.spec.ts` naming convention +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- Both positive and negative test cases are present for validation logic, parser modules, and utility functions +- Python tests include `setUp`/`tearDown` lifecycle methods where applicable +- TypeScript tests include `beforeEach`/`afterEach` lifecycle hooks where applicable + + +Claude Code MUST NOT skip or defer verification of test framework compliance, test naming conventions, fixture organization, and comprehensive test coverage (both positive and negative cases). All violations MUST be flagged during code review and CI pipeline execution. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-timing-parameters-waitseconds-72ef.md b/.actual/rules/cross-cutting-timing-parameters-waitseconds-72ef.md new file mode 100644 index 00000000000..729aeb67c28 --- /dev/null +++ b/.actual/rules/cross-cutting-timing-parameters-waitseconds-72ef.md @@ -0,0 +1,36 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Timing Parameters Waitseconds + +These rules are ALWAYS ACTIVE for all tool handler implementations in `src/tools/` that accept external input parameters, particularly those handling timing values, coordinates, and boolean flags. + +### Rules + +- **R-TIMING-001** MUST: Timing parameters (waitSeconds, delays) MUST be validated with minimum value constraints using `z.number().min()`. +- **R-TIMING-002** MUST: All tool handlers accepting external parameters MUST import Zod and define validation schemas using `z.object()` before the handler function. +- **R-TIMING-003** MUST: Input validation MUST use centralized validation utilities from `../utils/validation.js` for consistent error handling and messages. +- **R-TIMING-004** SHOULD: Coordinate parameters SHOULD use `.int().nonnegative()` validators; timing parameters SHOULD use `.min(0)` constraints. +- **R-TIMING-005** SHOULD: Optional flags SHOULD use `.optional().default()` patterns in schema definitions. +- **R-TIMING-006** SHOULD: TypeScript types SHOULD be exported using `z.infer` for use in function signatures and documentation. + +### Verify + +```bash +# Count Zod imports in tool handlers +grep -r "from 'zod'" src/tools/ | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/ | wc -l + +# Count validation utility imports +grep -r "../utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool handlers in `src/tools/` that accept external parameters import `'zod'` and define validation schemas +- Grep commands show consistent usage of `z.object()` schema definitions across tool implementations +- Validation utility imports from `../utils/validation.js` are present in all relevant tool files +- Timing parameters use `z.number().min()` constraints with appropriate minimum values +- TypeScript compilation succeeds, confirming type safety through schema inference + + +Claude Code MUST NOT skip or defer verification of these rules. All tool handlers accepting external parameters MUST conform to R-TIMING-001 through R-TIMING-006 before merge. Violations are treated as blocking issues requiring remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-based-integrations-2f80.md b/.actual/rules/cross-cutting-tool-based-integrations-2f80.md new file mode 100644 index 00000000000..ad10c2493e9 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-based-integrations-2f80.md @@ -0,0 +1,29 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Tool Based Integrations + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services, including real-time device integration servers, tool-based integration components that expose capabilities to external clients, bidirectional communication boundaries requiring protocol standardization, and integration points that require capability negotiation and discovery. + +### Rules + +- **R-MCP-001** MUST: Tool-based integrations MUST implement runtime tool lookup using collection search patterns (tools.find) to resolve tool names to handlers. + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization includes capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic uses collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files is mandatory. Code review checklist requiring capabilities declaration in server initialization is mandatory. Integration tests verifying tool discovery and invocation through MCP protocol are mandatory. CI pipeline MUST fail if integration servers lack MCP SDK imports or capabilities declaration. Code review MUST block merge if tool lookup patterns bypass protocol-standard discovery mechanisms. Architecture review is required for any custom protocol implementation in real-time integration boundaries. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-error-logs-faca.md b/.actual/rules/cross-cutting-tool-error-logs-faca.md new file mode 100644 index 00000000000..d1ea90d7bb4 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-error-logs-faca.md @@ -0,0 +1,37 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Tool Error Logs + +These rules are ALWAYS ACTIVE for MCP server implementations using @modelcontextprotocol/sdk, specifically for tool execution error handling and fatal error reporting within stdio-based MCP server communication. + +### Rules + +- **R-MCP-001** SHOULD: Tool error logs SHOULD include the tool name as context to facilitate debugging. +- **R-MCP-002** MUST: Tool execution errors MUST be logged using console.error with the format 'Tool error ({toolName}): {error.message}'. +- **R-MCP-003** MUST: Fatal server errors MUST be logged using console.error with the format 'Fatal error: {error}'. +- **R-MCP-004** MUST: The server MUST use stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr). +- **R-MCP-005** MUST: Tool execution MUST be wrapped in try-catch blocks with appropriate error logging. +- **R-MCP-006** MUST: Server infrastructure MUST be imported from @modelcontextprotocol/sdk/server/index.js and configured with name, version, and capabilities. + +### Verify + +```bash +# Verify tool error logging uses console.error with 'Tool error' prefix +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal errors are logged with console.error using 'Fatal error' prefix +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify server imports @modelcontextprotocol/sdk modules +grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts +``` + +**Accept when:** +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure +- Tool execution is wrapped in try-catch blocks +- stdio transport is configured from @modelcontextprotocol/sdk/server/stdio.js +- stderr is reserved for errors while stdout is reserved for protocol messages + + +Claude Code MUST NOT skip or defer verification. All rules must be verified through code review, grep-based verification commands, and runtime testing of error scenarios. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-errors-logged-54a4.md b/.actual/rules/cross-cutting-tool-errors-logged-54a4.md new file mode 100644 index 00000000000..42556a3755b --- /dev/null +++ b/.actual/rules/cross-cutting-tool-errors-logged-54a4.md @@ -0,0 +1,33 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Tool Errors Logged + +These rules are ALWAYS ACTIVE for all Android device integration implementations using the Model Context Protocol SDK, particularly MCP server implementations, tool registration patterns, and error handling in stdio-based communication channels. + +### Rules + +- **R-MCP-001** MUST: Tool errors MUST be logged using console.error with tool name and error message context. + +### Verify + +```bash +# Verify SDK imports are present +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . + +# Verify stdio transport is imported +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify console.error logging for tool errors +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capabilities with tools support +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + + +Clause R-MCP-001 verification is mandatory. Claude Code MUST NOT skip or defer verification of tool error logging patterns. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-execution-errors-9c42.md b/.actual/rules/cross-cutting-tool-execution-errors-9c42.md new file mode 100644 index 00000000000..a692ea0eea3 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-execution-errors-9c42.md @@ -0,0 +1,29 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Tool Execution Errors + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, specifically for tool execution error handling within the server capabilities boundary and fatal error conditions that terminate server operation. + +### Rules + +- **R-MCP-001** MUST: Tool execution errors MUST be logged using console.error with tool name context in the format 'Tool error ({name}): {message}' + +### Verify + +```bash +# Verify tool execution errors include console.error with tool name context +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal error handlers log to console.error +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify tool resolution pattern is present +grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + + +Claude Code MUST NOT skip or defer verification. All tool execution error handling MUST include console.error logging with tool name context before propagating or handling errors. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-handlers-implemented-e293.md b/.actual/rules/cross-cutting-tool-handlers-implemented-e293.md new file mode 100644 index 00000000000..39860996ff6 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-handlers-implemented-e293.md @@ -0,0 +1,37 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Tool Handlers Implemented + +These rules are ALWAYS ACTIVE for all tool handlers in `src/tools/` that expose public API contracts (capture, tapAt, findElementWithObstruction) and coordinate with ADB operations or filesystem I/O. + +### Rules + +- **R-ASYNC-001** MUST: Tool handlers MUST be implemented as async functions to coordinate with ADB operations and filesystem I/O. +- **R-ASYNC-002** MUST: All tool files in `src/tools/` MUST import Zod at the top: `import { z } from 'zod'`. +- **R-ASYNC-003** MUST: Validation schemas MUST be defined as const objects before handler functions using `z.object()` with field-level constraints. +- **R-ASYNC-004** MUST: Input validation MUST occur at the entry point of each handler using `schema.parse()` or `schema.safeParse()` before proceeding with handler logic. +- **R-ASYNC-005** MUST: All async handlers MUST properly await ADB operations and filesystem calls, and wrap execution in try/catch for error handling. +- **R-ASYNC-006** MUST: Handler functions and result types (e.g., FindElementResult) MUST be exported as named exports for API consumers. +- **R-ASYNC-007** SHOULD: Zod validation errors SHOULD be wrapped in error handling that transforms them into user-friendly messages with field-level details. +- **R-ASYNC-008** SHOULD: TypeScript types SHOULD be derived from Zod schemas using `z.infer<>` to ensure a single source of truth and prevent schema drift. + +### Verify + +```bash +# Count Zod imports in tool files +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` import Zod and define at least one `z.object()` schema. +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions. +- Verification commands show consistent usage of Zod schemas across at least 3 tool files. +- No tool handler lacks Zod validation or is implemented as a synchronous function. + + +Claude Code MUST NOT skip or defer verification. All tool handlers must pass the verification commands before acceptance. Pull requests adding new tools without Zod validation are blocked until schemas are added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-handlers-import-9bfd.md b/.actual/rules/cross-cutting-tool-handlers-import-9bfd.md new file mode 100644 index 00000000000..15c04426171 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-handlers-import-9bfd.md @@ -0,0 +1,38 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Tool Handlers Import + +These rules are ALWAYS ACTIVE for all tool handler files in `src/tools/` that expose public API contracts (capture, tapAt, findElementWithObstruction) requiring consistent input validation and asynchronous execution patterns. + +### Rules + +- **R-TOOL-001** MUST: Tool handlers MUST import core dependencies (zod, node:path, node:fs) and domain modules (../adb/adb.js, ../geometry/*) at the module level. +- **R-TOOL-002** MUST: All public API handlers (capture, tapAt, findElementWithObstruction) MUST be declared as async functions. +- **R-TOOL-003** MUST: Input validation MUST use Zod schemas defined as const objects before handler functions, using z.object() with field-level constraints. +- **R-TOOL-004** MUST: Validation MUST occur at the entry point of each handler using schema.parse() or schema.safeParse() before proceeding with handler logic. +- **R-TOOL-005** MUST: All async handlers MUST properly await ADB operations and filesystem calls, and wrap in try/catch for error handling. +- **R-TOOL-006** MUST: Both handler functions and result types (e.g., FindElementResult) MUST be exported as named exports for API consumers. +- **R-TOOL-007** SHOULD: Zod validation errors SHOULD be wrapped in error handling that transforms validation errors into user-friendly messages with field-level details. +- **R-TOOL-008** SHOULD: TypeScript types SHOULD be derived from Zod schemas using z.infer<> utility to ensure single source of truth and prevent schema drift. + +### Verify + +```bash +# Count Zod imports in tool handlers +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l +``` + +**Accept when:** +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files +- No tool handler exposes public API contracts without Zod validation schemas +- All async handlers include try/catch error handling for ADB and filesystem operations + + +Clause Code MUST NOT skip or defer verification. Pull requests adding new tools without Zod validation are blocked until schemas are added. Existing tools without validation must be flagged for refactoring in technical debt backlog. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-handlers-that-5b55.md b/.actual/rules/cross-cutting-tool-handlers-that-5b55.md new file mode 100644 index 00000000000..be569246af2 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-handlers-that-5b55.md @@ -0,0 +1,35 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Tool Handlers That + +These rules are ALWAYS ACTIVE for all tool handler implementations in `src/tools/` that accept external input parameters from MCP clients. + +### Rules + +- **R-ZOD-001** MUST: All tool handlers that accept external input parameters MUST define a Zod schema using `z.object()` to validate input structure and types. +- **R-ZOD-002** MUST: Import Zod and validation utilities at the top of each tool handler file: `import { z } from 'zod'` and validation utilities from `'../utils/validation.js'`. +- **R-ZOD-003** MUST: Define the input schema as a const using `z.object()` with appropriate field validators before the handler function. +- **R-ZOD-004** MUST: Use `.int().nonnegative()` for coordinate parameters, `.min(0)` for timing parameters, and `.optional().default()` for optional flags. +- **R-ZOD-005** MUST: Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages. +- **R-ZOD-006** SHOULD: Export the inferred TypeScript type using `z.infer` for use in function signatures and documentation. + +### Verify + +```bash +# Count Zod imports in tool handlers +grep -r "from 'zod'" src/tools/ | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/ | wc -l + +# Count validation utility imports +grep -r "../utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool handlers in `src/tools/` that accept external parameters import `'zod'` and define validation schemas +- Grep commands show consistent usage of `z.object()` schema definitions across tool implementations +- Validation utility imports from `'../utils/validation.js'` are present in all relevant tool files +- TypeScript compilation succeeds, confirming type safety through schema inference + + +Clause Code MUST NOT skip or defer verification. Pull requests adding tool handlers without Zod validation are rejected during code review. CI pipeline fails if tool files lack required validation imports. Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-implementations-export-cf91.md b/.actual/rules/cross-cutting-tool-implementations-export-cf91.md new file mode 100644 index 00000000000..fea83c11d9e --- /dev/null +++ b/.actual/rules/cross-cutting-tool-implementations-export-cf91.md @@ -0,0 +1,29 @@ +# Adopt Async Handler Pattern for Tool Operations: Tool Implementations Export + +These rules are ALWAYS ACTIVE for all tool implementations in the android-device-server MCP service, specifically all files in `src/tools/` that export handler functions for tool operations. + +### Rules + +- **R-ASYNC-001** MUST: Tool implementations MUST export an async handler function as the primary entry point for tool operations. + +### Verify + +```bash +# Count async handler exports in tool implementations +grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Verify adb operations use await for process coordination +grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Verify Zod validation schemas are defined +grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` export at least one async handler function +- All handlers that call adb operations use `await` for process coordination +- All tool modules define Zod validation schemas for input parameters + + +Clause Code MUST NOT skip or defer verification. All tool implementations must be reviewed for compliance with R-ASYNC-001 before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-implementations-import-f8f4.md b/.actual/rules/cross-cutting-tool-implementations-import-f8f4.md new file mode 100644 index 00000000000..4028991b611 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-implementations-import-f8f4.md @@ -0,0 +1,37 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Tool Implementations Import + +These rules are ALWAYS ACTIVE for all tool handler implementations in `src/tools/` that accept external input parameters from MCP clients. + +### Rules + +- **R-ZOD-001** MUST: Tool implementations MUST import validation utilities from `'../utils/validation.js'` for consistent error handling. +- **R-ZOD-002** MUST: Tool handlers that accept external parameters MUST define input schemas using `z.object()` with appropriate field validators before the handler function. +- **R-ZOD-003** MUST: Coordinate parameters MUST use `.int().nonnegative()` validators to enforce non-negative integer constraints. +- **R-ZOD-004** MUST: Timing parameters MUST use `.min(0)` validators to enforce valid timing ranges. +- **R-ZOD-005** MUST: Optional flags MUST use `.optional().default()` for proper default value handling. +- **R-ZOD-006** MUST: Tool implementations MUST import Zod at the top of each file: `import { z } from 'zod'`. +- **R-ZOD-007** SHOULD: Export inferred TypeScript types using `z.infer` for use in function signatures and documentation. +- **R-ZOD-008** SHOULD: Pass schemas to validation utilities to parse and validate input, handling validation errors with clear messages. + +### Verify + +```bash +# Count Zod imports in tool implementations +grep -r "from 'zod'" src/tools/ | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/ | wc -l + +# Count validation utility imports +grep -r "../utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool handlers in `src/tools/` that accept external parameters import `'zod'` and define validation schemas +- Grep commands show consistent usage of `z.object()` schema definitions across tool implementations +- Validation utility imports from `'../utils/validation.js'` are present in all relevant tool files +- TypeScript compilation succeeds, confirming type safety through schema inference + + +Claude Code MUST NOT skip or defer verification. All tool handlers accepting external parameters MUST conform to these rules before merge. Pull requests lacking Zod validation schemas are rejected during code review. CI pipeline fails if tool files lack required validation imports. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-implementations-modularized-ceec.md b/.actual/rules/cross-cutting-tool-implementations-modularized-ceec.md new file mode 100644 index 00000000000..c05d38b4596 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-implementations-modularized-ceec.md @@ -0,0 +1,39 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Tool Implementations Modularized + +These rules are ALWAYS ACTIVE for all Android device integration implementations using the Model Context Protocol, including server initialization, tool registration, error handling, and stdio-based transport communication. + +### Rules + +- **R-MCP-001** SHOULD: Tool implementations SHOULD be modularized by capability domain (e.g., ./tools/capture.js). +- **R-MCP-002** MUST: Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata. +- **R-MCP-003** MUST: Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance. +- **R-MCP-004** MUST: Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing. +- **R-MCP-005** MUST: Implement tool error handling with console.error logging that includes tool name and error message. +- **R-MCP-006** MUST: Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity. +- **R-MCP-007** MUST: Include capability declarations with tools support in server initialization. + +### Verify + +```bash +# Verify SDK imports are present +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify error handling patterns +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capability declarations +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Tool implementations are organized in ./tools/ directory by capability domain +- Validation utilities are organized in ./utils/ directory + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. Runtime monitoring MUST alert on tool execution failures without proper error logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-lookup-operations-3695.md b/.actual/rules/cross-cutting-tool-lookup-operations-3695.md new file mode 100644 index 00000000000..fdac2ff8a00 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-lookup-operations-3695.md @@ -0,0 +1,33 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Tool Lookup Operations + +These rules are ALWAYS ACTIVE for all MCP server implementations using @modelcontextprotocol/sdk, particularly tool execution error handling within the server capabilities boundary and stdio-based transport layer error reporting. + +### Rules + +- **R-MCP-001** SHOULD: Tool lookup operations using `tools.find(t => t.name === name)` SHOULD log errors when tool resolution fails. +- **R-MCP-002** MUST: All tool execution error paths MUST include `console.error` calls with tool name context using the prefix pattern `'Tool error ({name}):'`. +- **R-MCP-003** MUST: Fatal error handlers MUST log to `console.error` with the prefix `'Fatal error:'` before process termination. +- **R-MCP-004** MUST: Tool name MUST be captured from `tools.find(t => t.name === name)` result before execution to guarantee availability in error context. + +### Verify + +```bash +# Verify tool error logging with name context +grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ + +# Verify fatal error logging +grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ + +# Verify tool resolution pattern usage +grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ +``` + +**Accept when:** +- All tool execution error paths include `console.error` calls with tool name context +- Fatal error handlers log to `console.error` before process termination +- Tool resolution using `tools.find` pattern is followed by error handling with captured tool name +- Error messages follow the established prefix patterns (`'Tool error ({name}):'` and `'Fatal error:'`) + + +Claude Code MUST NOT skip or defer verification. All grep-based verification commands MUST pass before accepting changes to tool lookup and error handling code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-lookup-use-e58a.md b/.actual/rules/cross-cutting-tool-lookup-use-e58a.md new file mode 100644 index 00000000000..7ce6b445a11 --- /dev/null +++ b/.actual/rules/cross-cutting-tool-lookup-use-e58a.md @@ -0,0 +1,34 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Tool Lookup Use + +These rules are ALWAYS ACTIVE for all Android device integration implementations using the Model Context Protocol, specifically for MCP server implementations, tool registration and capability declaration, stdio-based transport communication, error handling and logging for tool execution, and type-safe protocol message handling. + +### Rules + +- **R-MCP-001** SHOULD: Tool lookup SHOULD use array find operations on registered tool collections by name. + +### Verify + +```bash +# Verify SDK imports are present +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . + +# Verify stdio transport is imported +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify tool error logging pattern +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capability declarations with tools support +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Tool implementations are organized in ./tools/ directory and validation utilities in ./utils/ directory + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. Runtime monitoring MUST alert on tool execution failures without proper error logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tool-modules-separate-8b2d.md b/.actual/rules/cross-cutting-tool-modules-separate-8b2d.md new file mode 100644 index 00000000000..34413a98f8f --- /dev/null +++ b/.actual/rules/cross-cutting-tool-modules-separate-8b2d.md @@ -0,0 +1,29 @@ +# Adopt Async Handler Pattern for Tool Operations: Tool Modules Separate + +These rules are ALWAYS ACTIVE for all tool implementations in the android-device-server MCP service, specifically all files in `src/tools/` that export handler functions for tool operations. + +### Rules + +- **R-ASYNC-001** SHOULD: Tool modules SHOULD separate validation schemas from handler implementation for clarity and reusability. + +### Verify + +```bash +# Count async handler function exports +grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count await calls on adb operations +grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count Zod validation schema definitions +grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` export at least one async handler function +- All handlers that call adb operations use `await` for process coordination +- All tool modules define Zod validation schemas for input parameters + + +Clause Code MUST NOT skip or defer verification. All tool implementations must follow the async handler pattern with separated validation schemas before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-type-definitions-imported-e555.md b/.actual/rules/cross-cutting-type-definitions-imported-e555.md new file mode 100644 index 00000000000..d7a093fa4a5 --- /dev/null +++ b/.actual/rules/cross-cutting-type-definitions-imported-e555.md @@ -0,0 +1,42 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Type Definitions Imported + +These rules are ALWAYS ACTIVE for all Android device MCP server implementations using the Model Context Protocol SDK for stdio-based transport and tool registration. + +### Rules + +- **R-MCP-001** MUST: Type definitions MUST be imported from @modelcontextprotocol/sdk/types.js to ensure protocol compliance. +- **R-MCP-002** MUST: Server construction MUST be imported from @modelcontextprotocol/sdk/server/index.js and initialized with name 'android-device-mcp' and version metadata. +- **R-MCP-003** MUST: StdioServerTransport MUST be imported from @modelcontextprotocol/sdk/server/stdio.js and connected to the server instance. +- **R-MCP-004** MUST: Tool error handling MUST use console.error logging that includes tool name and error message. +- **R-MCP-005** MUST: Server initialization MUST include capability declarations with tools support. +- **R-MCP-006** SHOULD: Tool implementations SHOULD be organized in ./tools/ directory and validation utilities in ./utils/ directory for modularity. + +### Verify + +```bash +# Verify SDK server imports +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . + +# Verify stdio transport imports +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify type definitions imports +grep -r "@modelcontextprotocol/sdk/types.js" --include="*.ts" --include="*.js" . + +# Verify tool error logging pattern +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capability declarations +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Tool implementations are organized in ./tools/ directory and validation utilities in ./utils/ directory + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-type-definitions-modelcontextprotocol-3508.md b/.actual/rules/cross-cutting-type-definitions-modelcontextprotocol-3508.md new file mode 100644 index 00000000000..a0929888d3f --- /dev/null +++ b/.actual/rules/cross-cutting-type-definitions-modelcontextprotocol-3508.md @@ -0,0 +1,29 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Type Definitions Modelcontextprotocol + +These rules are ALWAYS ACTIVE for all integration components that establish real-time communication boundaries with external devices or services, including real-time device integration servers, tool-based integration components, bidirectional communication boundaries, and integration points requiring capability negotiation and discovery. + +### Rules + +- **R-MCP-001** SHOULD: Type definitions from @modelcontextprotocol/sdk/types.js SHOULD be used to ensure protocol compliance in real-time device integration servers. + +### Verify + +```bash +# Verify MCP SDK imports in integration server files +grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l + +# Verify Server initialization includes capabilities declaration +grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l + +# Verify tool lookup or dispatch logic uses collection search patterns +grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l +``` + +**Accept when:** +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + + +Verification by static analysis scanning for @modelcontextprotocol/sdk imports in integration server files is mandatory. Code review must verify capabilities declaration in server initialization. Integration tests must verify tool discovery and invocation through MCP protocol. CI pipeline must fail if integration servers lack MCP SDK imports or capabilities declaration. Code review must block merge if tool lookup patterns bypass protocol-standard discovery mechanisms. Architecture review is required for any custom protocol implementation in real-time integration boundaries. Exception requests require performance benchmarks or technical constraints documentation and architecture review board evaluation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-typescript-libraries-use-0a85.md b/.actual/rules/cross-cutting-typescript-libraries-use-0a85.md new file mode 100644 index 00000000000..5e9320ad84f --- /dev/null +++ b/.actual/rules/cross-cutting-typescript-libraries-use-0a85.md @@ -0,0 +1,30 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Typescript Libraries Use + +These rules are ALWAYS ACTIVE for TypeScript library modules running in Node.js environments and Kotlin libraries using Retrofit for HTTP client functionality, designed for reuse across multiple applications or services. + +### Rules + +- **R-20-001** SHOULD: TypeScript libraries SHOULD use console.error with descriptive prefixes (e.g., 'Tool error (${name}):', 'Fatal error:') to distinguish error severity and context. + +### Verify + +```bash +# Check for console.error usage in TypeScript library code +grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" + +# Check for Response.error usage in Kotlin code +grep -r "Response\.error" --include="*.kt" src/ | head -20 + +# Verify no external logging framework imports in library code +grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l +``` + +**Accept when:** +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements +- Error messages include descriptive prefixes identifying library name, operation, and error category + + +Claude Code MUST NOT skip or defer verification. Code review checklist must verify use of platform-native error logging mechanisms. Dependency analysis in CI pipeline must flag external logging framework dependencies in library modules. Grep-based verification commands must check for console.error and Response.error patterns in library code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-typescript-test-files-3a62.md b/.actual/rules/cross-cutting-typescript-test-files-3a62.md new file mode 100644 index 00000000000..daaaea1d431 --- /dev/null +++ b/.actual/rules/cross-cutting-typescript-test-files-3a62.md @@ -0,0 +1,36 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Typescript Test Files + +These rules are ALWAYS ACTIVE for all TypeScript test files with `.spec.ts` or `.test.ts` extensions, and all Python test files with `test_` prefix or `_test` suffix in the codebase. + +### Rules + +- **R-TEST-001** MUST: TypeScript test files MUST use vitest as the test framework with describe/it block structure for test organization. +- **R-TEST-002** MUST: TypeScript test files MUST import describe, it, and expect from the 'vitest' package. +- **R-TEST-003** MUST: TypeScript test files MUST organize tests using nested describe blocks for logical grouping. +- **R-TEST-004** SHOULD: TypeScript test files SHOULD use beforeEach/afterEach for equivalent lifecycle management to Python's setUp/tearDown. +- **R-TEST-005** SHOULD: TypeScript test files SHOULD follow naming conventions with descriptive strings in it() blocks. + +### Verify + +```bash +# Verify vitest imports in TypeScript test files +grep -r 'from vitest import' --include='*.spec.ts' . +grep -r 'from vitest import' --include='*.test.ts' . + +# Verify describe/it structure in TypeScript test files +grep -r 'describe\|it' --include='*.spec.ts' . +grep -r 'describe\|it' --include='*.test.ts' . + +# Verify test execution in CI +# (CI pipeline test execution requiring vitest as test runner) +``` + +**Accept when:** +- All TypeScript test files with .spec.ts or .test.ts extension import from 'vitest' +- All TypeScript test files use describe/it structure for test organization +- Test execution in CI successfully runs vitest for TypeScript tests with passing results +- No TypeScript test files use jest or other competing frameworks without documented exception + + +Claude Code MUST NOT skip or defer verification of these rules when reviewing or creating TypeScript test files. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-typescript-test-files-dbef.md b/.actual/rules/cross-cutting-typescript-test-files-dbef.md new file mode 100644 index 00000000000..4f8bad340c8 --- /dev/null +++ b/.actual/rules/cross-cutting-typescript-test-files-dbef.md @@ -0,0 +1,40 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Typescript Test Files + +These rules are ALWAYS ACTIVE for all TypeScript test files and Python test modules within the configured scope. + +### Rules + +- **R-TEST-001** MUST: TypeScript test files MUST use the `*.spec.ts` naming convention. +- **R-TEST-002** MUST: Python test files MUST use the `test_*.py` naming convention. +- **R-TEST-003** MUST: TypeScript test files MUST import and use vitest with `describe`/`it` block structure for organizing test suites. +- **R-TEST-004** MUST: Python test files MUST inherit from `unittest.TestCase` and use `test_*` method naming convention. +- **R-TEST-005** SHOULD: Test fixtures SHOULD be organized in dedicated `fixtures/` subdirectories relative to test files. +- **R-TEST-006** SHOULD: TypeScript tests SHOULD use `beforeEach`/`afterEach` for test lifecycle management. +- **R-TEST-007** SHOULD: Python tests SHOULD use `setUp`/`tearDown` for test lifecycle management. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase base class +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests import vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files by naming convention +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +# Verify test file naming conventions +find . -path './node_modules' -prune -o -path './.git' -prune -o -name '*.spec.ts' -type f -print +find . -path './node_modules' -prune -o -path './.git' -prune -o -name 'test_*.py' -type f -print +``` + +**Accept when:** +- All Python test files use `unittest.TestCase` base class and `test_*` method naming convention +- All TypeScript test files use vitest with `describe`/`it` structure and `*.spec.ts` naming convention +- Test fixtures are organized in dedicated `fixtures/` directories with proper path resolution +- No test files exist with non-standard naming conventions (e.g., `*.test.ts`, `*_test.py`) + + +Claude Code MUST NOT skip or defer verification of test file naming conventions and framework usage. Pull requests introducing tests with non-standard frameworks or naming patterns MUST be rejected during code review. CI pipeline execution MUST fail if test files do not follow these conventions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-typescript-test-modules-d6b5.md b/.actual/rules/cross-cutting-typescript-test-modules-d6b5.md new file mode 100644 index 00000000000..71f8dd1e67a --- /dev/null +++ b/.actual/rules/cross-cutting-typescript-test-modules-d6b5.md @@ -0,0 +1,40 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Typescript Test Modules + +These rules are ALWAYS ACTIVE for all TypeScript test modules in `.claude/mcp/**/src/**/*.spec.ts` and Python test modules in `.github/scripts/*/test_*.py`. + +### Rules + +- **R-TEST-001** MUST: TypeScript test modules MUST use vitest with describe/it block structure for test organization. +- **R-TEST-002** MUST: Python test modules MUST use unittest with TestCase classes and test_* method naming convention. +- **R-TEST-003** MUST: Test fixtures MUST be organized in dedicated fixtures/ subdirectories relative to test files. +- **R-TEST-004** MUST: TypeScript test files MUST follow the *.spec.ts naming convention. +- **R-TEST-005** MUST: Python test files MUST follow the test_*.py naming convention. +- **R-TEST-006** SHOULD: Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup. + +### Verify + +```bash +# Verify Python tests use unittest.TestCase +grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py + +# Verify TypeScript tests import vitest +grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts + +# Count test files by convention +find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +# Verify test file naming conventions +find .github/scripts -name 'test_*.py' | wc -l +find .claude/mcp -name '*.spec.ts' | wc -l +``` + +**Accept when:** +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution +- Python tests import unittest and create test classes inheriting from unittest.TestCase +- TypeScript tests import describe, it, and expect from vitest + + +Claude Code MUST NOT skip or defer verification of test framework compliance. All test files must conform to the specified frameworks and naming conventions before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-typescript-tests-organize-9c5a.md b/.actual/rules/cross-cutting-typescript-tests-organize-9c5a.md new file mode 100644 index 00000000000..063090d8544 --- /dev/null +++ b/.actual/rules/cross-cutting-typescript-tests-organize-9c5a.md @@ -0,0 +1,37 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Typescript Tests Organize + +These rules are ALWAYS ACTIVE for all Python test files with `test_` prefix or `_test` suffix, and all TypeScript test files with `.spec.ts` or `.test.ts` extensions, including unit tests, integration tests, and functional tests in both languages. + +### Rules + +- **R-TEST-001** SHOULD: TypeScript tests SHOULD organize related test cases using nested describe blocks to provide hierarchical test structure. +- **R-TEST-002** MUST: Python test files MUST import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with `test_`. +- **R-TEST-003** MUST: TypeScript test files MUST import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping. +- **R-TEST-004** SHOULD: Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management. +- **R-TEST-005** SHOULD: Follow naming conventions with descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks. + +### Verify + +```bash +# Verify Python test files use unittest +grep -r 'import unittest' --include='test_*.py' .github/scripts/ + +# Verify TypeScript test files use vitest +grep -r 'from vitest import' --include='*.spec.ts' .claude/ + +# Verify Python test classes inherit from unittest.TestCase +grep -r 'class.*unittest\.TestCase' --include='test_*.py' . + +# Verify TypeScript tests use describe/it structure +grep -r 'describe\|it' --include='*.spec.ts' . +``` + +**Accept when:** +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results +- No plain assert statements are used in unittest.TestCase classes (use unittest assertion methods instead) + + +Claude Code MUST NOT skip or defer verification. All test files in scope MUST comply with the specified framework requirements before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-use-alternative-collection-7913.md b/.actual/rules/cross-cutting-use-alternative-collection-7913.md new file mode 100644 index 00000000000..478ce848d7a --- /dev/null +++ b/.actual/rules/cross-cutting-use-alternative-collection-7913.md @@ -0,0 +1,37 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Use Alternative Collection + +These rules are ALWAYS ACTIVE for all TypeScript, JavaScript, and Python files that perform in-memory data queries, particularly in test specifications, automation scripts, and utilities that parse system output or configuration data. + +### Rules + +- **R-COLL-001** MUST: Use Array.find() for single-element lookup operations with predicate functions in TypeScript/JavaScript code. +- **R-COLL-002** MAY: Use alternative collection methods (filter, some, every) when query semantics require multiple results or boolean existence checks. +- **R-COLL-003** MUST: Use TypeScript strict mode to enforce null/undefined handling for .find() return values. +- **R-COLL-004** SHOULD: Create utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication. +- **R-COLL-005** MUST: For Python code, use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find(). +- **R-COLL-006** SHOULD: Avoid Array.filter() followed by index access [0] for single-element lookup due to unnecessary performance overhead. +- **R-COLL-007** MAY: Use Map or Object lookup with key-based access for frequently queried large collections where pre-indexing justifies overhead. + +### Verify + +```bash +# Identify Array.find() usage with predicate functions in TypeScript/JavaScript +grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . + +# Identify Set.add() operations in Python scripts for collection building +grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' + +# Verify test suite passes with window lookup operations +npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' +``` + +**Accept when:** +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method +- TypeScript strict null checks are enabled and enforced +- Code review checklist verification of collection query patterns is documented + + +Claude Code MUST NOT skip or defer verification. All three verify commands must execute successfully before accepting code that modifies collection query patterns. Performance-critical path exceptions require inline benchmark documentation and explicit approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-use-array-find-3f88.md b/.actual/rules/cross-cutting-use-array-find-3f88.md new file mode 100644 index 00000000000..5ed33ac116a --- /dev/null +++ b/.actual/rules/cross-cutting-use-array-find-3f88.md @@ -0,0 +1,33 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Use Array Find + +These rules are ALWAYS ACTIVE for all JavaScript/TypeScript files and Python automation scripts that query in-memory data structures, particularly when working with parsed system output, configuration data, and test fixtures. + +### Rules + +- **R-FIND-001** SHOULD: Use Array.find() with predicate functions for locating single elements in JavaScript/TypeScript collections when searching by property equality. +- **R-FIND-002** SHOULD: Use next(filter(predicate, collection), default) as the equivalent pattern in Python code for single-element lookup operations. +- **R-FIND-003** MUST: Enforce TypeScript strict mode to enforce null/undefined handling for .find() return values. +- **R-FIND-004** SHOULD: Create utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication. +- **R-FIND-005** MAY: Use manual iteration with conditional breaks only in performance-critical paths where profiling demonstrates measurable impact compared to Array.find(). + +### Verify + +```bash +# Identify Array.find() usage with predicate functions in TypeScript/JavaScript +grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . + +# Identify Set.add() usage in Python scripts for collection building +grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' + +# Verify test suite passes with window lookup operations +npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' +``` + +**Accept when:** +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + + +Clause Code MUST NOT skip or defer verification. Code review checklist MUST include verification of collection query patterns. ESLint rules MUST be configured to discourage manual iteration where Array methods are applicable. Test coverage requirements MUST ensure query operations are tested with expected and missing elements. Performance-critical path exceptions MUST include inline comments with benchmark data comparing Array.find() vs manual iteration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-use-custom-validation-0705.md b/.actual/rules/cross-cutting-use-custom-validation-0705.md new file mode 100644 index 00000000000..c9f6d72bcf6 --- /dev/null +++ b/.actual/rules/cross-cutting-use-custom-validation-0705.md @@ -0,0 +1,31 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Use Custom Validation + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-VAL-001** MAY: APIs MAY use custom validation functions for complex business rules that cannot be expressed through declarative schema constraints. + +### Verify + +```bash +# Verify schema validation usage across TypeScript tools +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Verify JSON validation in Python scripts +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation-specific tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions +- For TypeScript tools, validation schemas are defined using zod's z.object() with explicit types +- For Python scripts, json.load() is used with subsequent schema validation or a Python schema validation library + + +Claude Code MUST NOT skip or defer verification. All public API endpoints accepting external input MUST implement schema-based validation before processing. Code review and CI/CD pipeline checks are mandatory for all new endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-use-set-add-a890.md b/.actual/rules/cross-cutting-use-set-add-a890.md new file mode 100644 index 00000000000..fd3f6330984 --- /dev/null +++ b/.actual/rules/cross-cutting-use-set-add-a890.md @@ -0,0 +1,36 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Use Set Add + +These rules are ALWAYS ACTIVE for all TypeScript, JavaScript, and Python files performing in-memory data queries, collection building, and membership testing operations across test specifications, automation scripts, and operational code. + +### Rules + +- **R-COLL-001** SHOULD: Use Set.add() for building unique collections when membership testing or duplicate prevention is required. +- **R-COLL-002** SHOULD: Use Array.find() with predicate functions for single-element lookup operations to improve code readability and semantic clarity. +- **R-COLL-003** MUST: Enforce TypeScript strict mode to enforce null/undefined handling for .find() return values. +- **R-COLL-004** SHOULD: Create utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication. +- **R-COLL-005** SHOULD: Use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find() in Python code. +- **R-COLL-006** MAY: Use manual iteration with conditional breaks only in performance-critical paths where profiling demonstrates measurable impact. + +### Verify + +```bash +# Identify Array.find() usage with predicate functions in TypeScript/JavaScript +grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . + +# Identify Set.add() usage for collection building in Python +grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' + +# Verify test suite passes for dumpsys parser with window lookup operations +npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' +``` + +**Accept when:** +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method +- TypeScript strict null checks are enabled and enforced in tsconfig.json +- Code review checklist includes verification of collection query patterns + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for code review and must be checked before merge. Performance-critical path exceptions require inline documentation with benchmark data comparing Array.find() vs manual iteration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-failures-result-13ac.md b/.actual/rules/cross-cutting-validation-failures-result-13ac.md new file mode 100644 index 00000000000..061d4775f62 --- /dev/null +++ b/.actual/rules/cross-cutting-validation-failures-result-13ac.md @@ -0,0 +1,30 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Validation Failures Result + +These rules are ALWAYS ACTIVE for all public and external API endpoints that accept external input, including MCP tool handlers, GitHub automation scripts, XML parsing functions, and any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data. + +### Rules + +- **R-VAL-001** MUST: Validation failures MUST result in early rejection with descriptive error messages that do not expose internal implementation details. + +### Verify + +```bash +# Verify schema validation usage across TypeScript tools +grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l + +# Verify JSON validation in Python scripts +grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l + +# Run validation-specific tests +npm test -- --grep 'validation' || python -m pytest -k validation +``` + +**Accept when:** +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions +- Validation error messages are descriptive but do not expose internal implementation details + + +Claude Code MUST NOT skip or defer verification. All public API endpoints accepting external input MUST implement schema-based validation with early rejection and descriptive error messages. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-schemas-define-a0dd.md b/.actual/rules/cross-cutting-validation-schemas-define-a0dd.md new file mode 100644 index 00000000000..8b5720103c0 --- /dev/null +++ b/.actual/rules/cross-cutting-validation-schemas-define-a0dd.md @@ -0,0 +1,42 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Validation Schemas Define + +These rules are ALWAYS ACTIVE for all tool handlers in android-device-server, XML parsing operations, GitHub automation scripts, public API contracts, and command-line argument parsing that process external inputs. + +### Rules + +- **R-VAL-001** SHOULD: Validation schemas SHOULD define default values for optional parameters (e.g., .default(true), .default(2)) to ensure predictable behavior. +- **R-VAL-002** MUST: All tool handlers in android-device-server (capture.ts, tap-at.ts) MUST define zod schemas with explicit type constraints before processing inputs. +- **R-VAL-003** MUST: XML parsing operations MUST use fast-xml-parser with error handling for malformed input to prevent injection attacks and malformed data propagation. +- **R-VAL-004** MUST: JSON configuration loading in GitHub automation scripts MUST include exception handling and validation of required fields before accessing. +- **R-VAL-005** MUST: Public API contracts exposed through ToolDefinition interfaces MUST include input validation schemas at API boundaries. +- **R-VAL-006** MUST: Validation errors MUST be sanitized to prevent information disclosure vulnerabilities; detailed errors logged internally, generic messages returned to users. +- **R-VAL-007** SHOULD: Complex nested schemas SHOULD be profiled for performance impact on high-frequency API endpoints and optimized or cached as needed. +- **R-VAL-008** MUST: Validation behavior across TypeScript (zod) and Python (json.load) MUST be verified equivalent through integration tests. + +### Verify + +```bash +# Count zod schema definitions in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count fast-xml-parser usage in parsers +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Count json.load usage in GitHub scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation test suite +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML +- Error sanitization layer maps validation errors to generic user-facing messages while logging detailed errors internally +- Integration tests verify equivalent validation behavior across TypeScript and Python language boundaries + + +Clause Code MUST NOT skip or defer verification. All pull requests introducing new API endpoints or tool handlers without input validation schemas are blocked in code review. Runtime validation errors must be logged with request context for security monitoring. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-schemas-include-3c4f.md b/.actual/rules/cross-cutting-validation-schemas-include-3c4f.md new file mode 100644 index 00000000000..5653a951e37 --- /dev/null +++ b/.actual/rules/cross-cutting-validation-schemas-include-3c4f.md @@ -0,0 +1,38 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Validation Schemas Include + +These rules are ALWAYS ACTIVE for all tool handlers in `src/tools/` that expose public API contracts (capture, tapAt, findElementWithObstruction) and coordinate with external ADB processes or filesystem operations. + +### Rules + +- **R-ASYNC-VAL-001** MUST: All public API tool handlers import Zod at the module level with `import { z } from 'zod'`. +- **R-ASYNC-VAL-002** MUST: All public API tool handlers define validation schemas as `const` objects using `z.object()` with field-level constraints before the handler function. +- **R-ASYNC-VAL-003** MUST: All public API tool handlers are declared as `async` functions that properly await ADB operations and filesystem calls. +- **R-ASYNC-VAL-004** MUST: Input validation occurs at the entry point of each handler using `schema.parse()` or `schema.safeParse()` before proceeding with handler logic. +- **R-ASYNC-VAL-005** MUST: All async handlers wrap ADB and filesystem operations in try/catch blocks for error handling. +- **R-ASYNC-VAL-006** MUST: Public API contracts (handler functions and result types) are exported as named exports for API consumers. +- **R-ASYNC-VAL-007** MAY: Validation schemas MAY include constraints such as `.int()`, `.nonnegative()`, `.min()` to enforce domain-specific invariants. +- **R-ASYNC-VAL-008** SHOULD: Use Zod's `z.infer<>` utility to derive TypeScript types from schemas, ensuring single source of truth and preventing schema drift. + +### Verify + +```bash +# Count Zod imports in tool files +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` import Zod and define at least one `z.object()` schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as `async` functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files +- All handlers validate inputs before proceeding with execution logic +- All async operations are properly awaited and wrapped in error handling + + +Clause Code MUST NOT skip or defer verification. Pull requests adding new tools without Zod validation are blocked until schemas are added. Existing tools without validation are flagged for refactoring in technical debt backlog. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-schemas-use-9f64.md b/.actual/rules/cross-cutting-validation-schemas-use-9f64.md new file mode 100644 index 00000000000..c6e355dfb8f --- /dev/null +++ b/.actual/rules/cross-cutting-validation-schemas-use-9f64.md @@ -0,0 +1,37 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Validation Schemas Use + +These rules are ALWAYS ACTIVE for all tool handlers in `src/tools/` that expose public API contracts, including input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions, and async coordination with ADB shell commands and filesystem operations. + +### Rules + +- **R-VALIDATION-001** MUST: Validation schemas MUST use `z.object()` with typed fields (`z.number()`, `z.boolean()`, `z.string()`) and MUST specify defaults using `.default()` where appropriate. +- **R-VALIDATION-002** MUST: All public API handlers (capture, tapAt, findElementWithObstruction) MUST be declared as async functions. +- **R-VALIDATION-003** MUST: Import Zod at the top of each tool module: `import { z } from 'zod'`. +- **R-VALIDATION-004** MUST: Define validation schemas as const objects before handler functions, using `z.object()` with field-level constraints. +- **R-VALIDATION-005** MUST: Use `schema.parse()` or `schema.safeParse()` at the entry point of each handler to validate inputs before proceeding. +- **R-VALIDATION-006** MUST: All async handlers MUST properly await ADB operations and filesystem calls, and wrap in try/catch for error handling. +- **R-VALIDATION-007** MUST: Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers. +- **R-VALIDATION-008** SHOULD: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details. +- **R-VALIDATION-009** SHOULD: Use Zod's `z.infer<>` utility to derive TypeScript types from schemas, ensuring single source of truth. + +### Verify + +```bash +# Count Zod imports in tool files +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` import Zod and define at least one `z.object()` schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + + +Claude Code MUST NOT skip or defer verification. Pull requests adding new tools without Zod validation are blocked until schemas are added. Existing tools without validation are flagged for refactoring in technical debt backlog. Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-utilities-centralized-f02d.md b/.actual/rules/cross-cutting-validation-utilities-centralized-f02d.md new file mode 100644 index 00000000000..4aac1c81fed --- /dev/null +++ b/.actual/rules/cross-cutting-validation-utilities-centralized-f02d.md @@ -0,0 +1,42 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Validation Utilities Centralized + +These rules are ALWAYS ACTIVE for all TypeScript tool handlers, XML parsing operations, Python GitHub automation scripts, and public API endpoints that process external inputs including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments. + +### Rules + +- **R-VAL-001** SHOULD: Validation utilities SHOULD be centralized in dedicated modules (e.g., utils/validation.ts) and reused across tool implementations. +- **R-VAL-002** MUST: All tool handlers in android-device-server (capture.ts, tap-at.ts) MUST define zod schemas with explicit type constraints for all required and optional parameters before processing inputs. +- **R-VAL-003** MUST: XML parsing operations for UI hierarchy extraction MUST use fast-xml-parser with appropriate error handling for malformed input and attribute handling based on UI hierarchy requirements. +- **R-VAL-004** MUST: GitHub automation scripts processing PR metadata and JSON configs MUST wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions. +- **R-VAL-005** MUST: Public API contracts exposed through ToolDefinition interfaces MUST include input validation at API boundaries using centralized validation utilities. +- **R-VAL-006** MUST: Command-line argument parsing using argparse MUST validate inputs against defined schemas before processing. +- **R-VAL-007** SHOULD: Validation error messages SHOULD be sanitized to prevent information disclosure vulnerabilities, mapping validation errors to generic user-facing messages while logging detailed errors internally. +- **R-VAL-008** MAY: Internal function parameters with compile-time type guarantees MAY be exempted from schema validation when type safety is guaranteed by TypeScript's type system. + +### Verify + +```bash +# Count zod schema definitions in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count fast-xml-parser usage in parsers +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Count json.load() calls in GitHub scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation tests +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML +- Error sanitization layer maps validation errors to generic user-facing messages +- Integration tests verify validation error responses for invalid inputs across all public APIs + + +Clause Code MUST NOT skip or defer verification. All new API endpoints and tool handlers require zod schema definitions. Pull requests introducing external input processing without input validation schemas are blocked in code review. Quarterly security audits identify unvalidated input paths and create remediation tickets. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-utilities-imported-0c4d.md b/.actual/rules/cross-cutting-validation-utilities-imported-0c4d.md new file mode 100644 index 00000000000..054a0b1fdaa --- /dev/null +++ b/.actual/rules/cross-cutting-validation-utilities-imported-0c4d.md @@ -0,0 +1,41 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Validation Utilities Imported + +These rules are ALWAYS ACTIVE for all tool handlers in `src/tools/` that expose public API contracts (capture, tapAt, findElementWithObstruction) requiring input validation and asynchronous execution with external ADB processes and filesystem operations. + +### Rules + +- **R-ASYNC-VAL-001** MUST: Validation utilities MUST be imported from `'../utils/validation.js'` to promote reuse across tool implementations. +- **R-ASYNC-VAL-002** MUST: All public API handlers (capture, tapAt, findElementWithObstruction) MUST be declared as async functions. +- **R-ASYNC-VAL-003** MUST: Zod MUST be imported at the top of each tool module: `import { z } from 'zod'`. +- **R-ASYNC-VAL-004** MUST: Validation schemas MUST be defined as const objects before handler functions using `z.object()` with field-level constraints. +- **R-ASYNC-VAL-005** MUST: Schema validation MUST occur at the entry point of each handler using `schema.parse()` or `schema.safeParse()` before proceeding with handler logic. +- **R-ASYNC-VAL-006** MUST: All async handlers MUST properly await ADB operations and filesystem calls, and wrap in try/catch for error handling. +- **R-ASYNC-VAL-007** MUST: Both handler functions and result types (e.g., FindElementResult) MUST be exported as named exports for API consumers. +- **R-ASYNC-VAL-008** SHOULD: Zod validation errors SHOULD be wrapped in error handling that transforms validation errors into user-friendly messages with field-level details. +- **R-ASYNC-VAL-009** SHOULD: TypeScript types SHOULD be derived from Zod schemas using `z.infer<>` utility to ensure single source of truth and prevent schema drift. + +### Verify + +```bash +# Count Zod imports across tool files +grep -r "from 'zod'" src/tools/ | wc -l + +# Count async handler declarations +grep -r "async.*handler\|async function" src/tools/*.ts | wc -l + +# Count z.object() schema definitions +grep -r "z\.object({" src/tools/*.ts | wc -l + +# Verify validation utilities are imported from correct path +grep -r "from.*utils/validation" src/tools/ | wc -l +``` + +**Accept when:** +- All tool files in `src/tools/` import Zod and define at least one `z.object()` schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files +- Validation utilities are imported from `'../utils/validation.js'` in all tool implementations + + +Clause Code MUST NOT skip or defer verification. Pull requests adding new tools without Zod validation are blocked until schemas are added. Existing tools without validation are flagged for refactoring in technical debt backlog. Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-validation-utilities-separated-c0da.md b/.actual/rules/cross-cutting-validation-utilities-separated-c0da.md new file mode 100644 index 00000000000..16709ea8eaf --- /dev/null +++ b/.actual/rules/cross-cutting-validation-utilities-separated-c0da.md @@ -0,0 +1,38 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Validation Utilities Separated + +These rules are ALWAYS ACTIVE for all Android device integration implementations using the Model Context Protocol, specifically for MCP server implementations, tool registration and capability declaration, stdio-based transport communication, error handling and logging for tool execution, and type-safe protocol message handling. + +### Rules + +- **R-MCP-001** SHOULD: Validation utilities SHOULD be separated into dedicated modules (e.g., ./utils/validation.js) +- **R-MCP-002** MUST: Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- **R-MCP-003** MUST: Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- **R-MCP-004** MUST: Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- **R-MCP-005** MUST: Implement tool error handling with console.error logging that includes tool name and error message +- **R-MCP-006** SHOULD: Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity +- **R-MCP-007** MUST: Server initialization MUST include capability declarations with tools support + +### Verify + +```bash +# Verify SDK imports are present +grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . + +# Verify error handling patterns +grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . + +# Verify capability declarations +grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . +``` + +**Accept when:** +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing +- Validation utilities are organized in dedicated modules separate from tool implementations + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for @modelcontextprotocol/sdk import statements is mandatory. Code review verification of server initialization patterns and capability declarations is mandatory. Automated testing of error logging output format and content is mandatory. CI pipeline MUST fail if SDK imports are missing or incorrect. Code review MUST block merge if error handling does not follow console.error patterns. Runtime monitoring MUST alert on tool execution failures without proper error logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodel-classes-annotated-37e9.md b/.actual/rules/cross-cutting-viewmodel-classes-annotated-37e9.md new file mode 100644 index 00000000000..6b0b745c151 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodel-classes-annotated-37e9.md @@ -0,0 +1,40 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Viewmodel Classes Annotated + +These rules are ALWAYS ACTIVE for all Android ViewModel classes and Activity components within the application codebase. + +### Rules + +- **R-HILT-001** MUST: All ViewModel classes MUST be annotated with @HiltViewModel to enable constructor injection and proper scoping. +- **R-HILT-002** MUST: All Activity subclasses (ComponentActivity, AppCompatActivity) MUST be annotated with @AndroidEntryPoint to enable field injection of required dependencies. +- **R-HILT-003** MUST: The Application class MUST be annotated with @HiltAndroidApp to initialize the Hilt dependency graph. +- **R-HILT-004** MUST: All dependencies in ViewModel classes MUST use constructor injection with @Inject annotation, not field injection. +- **R-HILT-005** SHOULD: Activities SHOULD use androidx.activity.viewModels() delegate to obtain Hilt-injected ViewModels with proper scoping. +- **R-HILT-006** SHOULD: Dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) SHOULD be documented in module provider methods. + +### Verify + +```bash +# Verify all Activity classes contain @AndroidEntryPoint annotation +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Verify all ViewModel classes contain @HiltViewModel annotation +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Verify constructor injection usage with @Inject +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application class is annotated with @HiltAndroidApp +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle +- No manual dependency instantiation exists in Hilt-enabled components + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for ViewModel and Activity components. Violations must be caught during code review and CI build verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-annotated-hiltviewmodel-b639.md b/.actual/rules/cross-cutting-viewmodels-annotated-hiltviewmodel-b639.md new file mode 100644 index 00000000000..008c444909a --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-annotated-hiltviewmodel-b639.md @@ -0,0 +1,38 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Annotated Hiltviewmodel + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the app module, including UI state management for authentication flows, application-level state coordination, and state objects representing dialog states, loading states, and error states. + +### Rules + +- **R-HILT-VM-001** MUST: All ViewModels MUST be annotated with @HiltViewModel to enable dependency injection through Hilt framework. +- **R-HILT-VM-002** MUST: State updates MUST use mutableStateFlow.update with copy operations rather than direct value assignment to ensure atomicity and thread-safety. +- **R-HILT-VM-003** MUST: State classes MUST implement Parcelable interface for restoration support across process death. +- **R-HILT-VM-004** MUST: Asynchronous operations MUST execute within viewModelScope for proper lifecycle management and coroutine cancellation. +- **R-HILT-VM-005** SHOULD: State SHOULD be exposed to UI as StateFlow using stateIn or asStateFlow to prevent external mutations. +- **R-HILT-VM-006** SHOULD: State SHOULD be defined as immutable data classes (val properties) with sealed classes for variant states like dialogs. + +### Verify + +```bash +# Count @HiltViewModel annotations in ViewModel files +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + + +Clause Code MUST NOT skip or defer verification of these rules during code review and CI pipeline checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-3cae.md b/.actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-3cae.md new file mode 100644 index 00000000000..e5e63e334a0 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-3cae.md @@ -0,0 +1,44 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Extend Baseviewmodel + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the app module, including UI state management for authentication flows, application-level state coordination, and state objects representing dialog states, loading states, and error states. + +### Rules + +- **R-HILT-VM-001** SHOULD: ViewModels SHOULD extend BaseViewModel when common functionality is required across multiple ViewModels. +- **R-HILT-VM-002** MUST: All ViewModel classes MUST be annotated with @HiltViewModel and use constructor injection for dependencies. +- **R-HILT-VM-003** MUST: State MUST be defined as immutable Parcelable data classes with all properties declared as val. +- **R-HILT-VM-004** MUST: All state mutations MUST use mutableStateFlow.update { it.copy(property = newValue) } pattern to ensure atomicity and prevent direct value assignment. +- **R-HILT-VM-005** MUST: Asynchronous operations MUST execute within viewModelScope for proper lifecycle management and coroutine cancellation. +- **R-HILT-VM-006** MUST: State MUST be exposed to UI as StateFlow using stateIn or asStateFlow to prevent external mutations. +- **R-HILT-VM-007** SHOULD: State classes SHOULD implement Parcelable interface for restoration support across process death. +- **R-HILT-VM-008** SHOULD: Complex state transitions SHOULD use sealed classes for variant states like dialogs and loading states. + +### Verify + +```bash +# Count @HiltViewModel annotations +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Detect direct MutableStateFlow value assignments (anti-pattern) +grep -r 'mutableStateFlow\.value\s*=' app/src/main/kotlin --include='*ViewModel.kt' +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management +- No direct MutableStateFlow value assignments are detected in the codebase + + +Claude Code MUST NOT skip or defer verification of these rules. All ViewModel implementations MUST comply with R-HILT-VM-002, R-HILT-VM-004, R-HILT-VM-005, and R-HILT-VM-006 as mandatory requirements. Violations MUST be flagged during code review and CI pipeline checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-cc3e.md b/.actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-cc3e.md new file mode 100644 index 00000000000..8f7082c4634 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-extend-baseviewmodel-cc3e.md @@ -0,0 +1,41 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Viewmodels Extend Baseviewmodel + +These rules are ALWAYS ACTIVE for all Activity and ViewModel implementations serving as application entry points, including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI. + +### Rules + +- **R-ENTRY-001** MUST: All Activity subclasses serving as application entry points SHALL extend either `androidx.activity.ComponentActivity` or `androidx.appcompat.app.AppCompatActivity`. +- **R-ENTRY-002** MUST: All Activity classes requiring dependency injection SHALL be annotated with `@AndroidEntryPoint`. +- **R-ENTRY-003** SHOULD: ViewModels SHOULD extend `BaseViewModel` and be annotated with `@HiltViewModel` to standardize state management and dependency injection patterns. +- **R-ENTRY-004** MUST: ViewModel instances in Activities SHALL be obtained through `androidx.activity.viewModels()` delegation to ensure proper lifecycle scoping. +- **R-ENTRY-005** MUST: Intent handling logic SHALL be implemented in `onCreate` and `onNewIntent` methods, routing Intent data to ViewModel through sealed action classes. +- **R-ENTRY-006** MUST: Specialized Activity implementations for distinct system integration points (credential provider, auth callback, autofill callback, main UI) SHALL maintain clear architectural boundaries. +- **R-ENTRY-007** MAY: Legacy Activity implementations may temporarily use `android.app.Activity` base class during migration to AndroidX (EXC-001). + +### Verify + +```bash +# Count Activity classes extending ComponentActivity or AppCompatActivity +grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count Activity classes annotated with @AndroidEntryPoint +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count ViewModel classes annotated with @HiltViewModel +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Count Activity classes using androidx.activity.viewModels delegation +grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l +``` + +**Accept when:** +- All Activity classes extend either `androidx.activity.ComponentActivity` or `androidx.appcompat.app.AppCompatActivity` +- All Activity classes requiring dependency injection are annotated with `@AndroidEntryPoint` +- All ViewModel classes are annotated with `@HiltViewModel` and obtained through `androidx.activity.viewModels()` delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) +- Intent handling is routed to ViewModels through sealed action classes +- AndroidManifest.xml Activity declarations match implementation files with appropriate intent filters + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for Activity base class inheritance patterns, lint rules checking @AndroidEntryPoint annotation presence, code review verification of ViewModel instantiation, and CI pipeline checks for AndroidManifest Activity declarations are mandatory. Violations result in CI build failure, lint warnings escalated to errors, and code review blocks. Exceptions require architecture team approval and tracking issues with migration plans. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-handling-android-4582.md b/.actual/rules/cross-cutting-viewmodels-handling-android-4582.md new file mode 100644 index 00000000000..9cb7470c4a4 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-handling-android-4582.md @@ -0,0 +1,34 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Handling Android + +These rules are ALWAYS ACTIVE for all Android ViewModels handling Intent-based public API interactions, including credential provider APIs, authentication callback processing, and autofill service coordination. + +### Rules + +- **R-HILT-001** MUST: ViewModels handling Android Intent-based public API interactions MUST use @HiltViewModel annotation for dependency injection. +- **R-HILT-002** MUST: All public API boundary ViewModels MUST extend BaseViewModel and inject dependencies through constructor parameters annotated with @Inject. +- **R-HILT-003** MUST: Each public API ViewModel MUST define sealed action types (e.g., CredentialProviderAction, AuthCallbackAction) for type-safe contract enforcement between system APIs and application logic. +- **R-HILT-004** SHOULD: Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel. +- **R-HILT-005** SHOULD: Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies. + +### Verify + +```bash +# Verify @HiltViewModel annotation on public API boundary ViewModels +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l + +# Verify sealed action types are defined +grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l + +# Verify public API ViewModels extend BaseViewModel and use @HiltViewModel +find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l +``` + +**Accept when:** +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters +- Repository or manager layer components are used for Intent processing logic + + +Clause Code MUST NOT skip or defer verification. All public API boundary ViewModels must comply with R-HILT-001 through R-HILT-003 (MUST rules). Violations block CI builds and code review merges. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-handling-external-c129.md b/.actual/rules/cross-cutting-viewmodels-handling-external-c129.md new file mode 100644 index 00000000000..d711bf4f5ef --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-handling-external-c129.md @@ -0,0 +1,35 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Handling External + +These rules are ALWAYS ACTIVE for all Android ViewModels handling external API contracts at public API boundaries, including credential provider APIs, authentication callback Intents, and autofill service interactions. + +### Rules + +- **R-HILT-001** MUST: All ViewModels handling external API contracts MUST use the @HiltViewModel annotation for dependency injection. +- **R-HILT-002** MUST: All public API boundary ViewModels MUST extend BaseViewModel and inject dependencies through constructor parameters annotated with @Inject. +- **R-HILT-003** SHOULD: ViewModels handling external API contracts SHOULD use data classes for Intent payload representation. +- **R-HILT-004** SHOULD: ViewModels processing Intent-based contracts SHOULD define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic. +- **R-HILT-005** SHOULD: Intent processing logic SHOULD be delegated to repository or manager layer components rather than embedding Android framework calls directly in ViewModel. + +### Verify + +```bash +# Verify @HiltViewModel annotation on public API boundary ViewModels +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l + +# Verify sealed action types are defined +grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l + +# Verify public API ViewModels extend BaseViewModel and use @HiltViewModel +find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l +``` + +**Accept when:** +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters +- Intent payload data is represented using data classes +- Repository or manager layer components handle Intent processing logic + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for public API boundary ViewModels. Violations must be caught during code review and CI pipeline verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-inject-multiple-c778.md b/.actual/rules/cross-cutting-viewmodels-inject-multiple-c778.md new file mode 100644 index 00000000000..c1aa792df23 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-inject-multiple-c778.md @@ -0,0 +1,35 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Inject Multiple + +These rules are ALWAYS ACTIVE for all Android ViewModels serving as public API boundaries for system integrations, including credential provider APIs, authentication callback Intents, and autofill service interactions. + +### Rules + +- **R-HILT-001** MAY: ViewModels MAY inject multiple repository or manager dependencies when coordinating complex external API workflows. +- **R-HILT-002** MUST: All public API boundary ViewModels handling Intent-based interactions MUST be annotated with @HiltViewModel. +- **R-HILT-003** MUST: All public API ViewModels MUST define sealed action types for type-safe contract enforcement between system APIs and application logic. +- **R-HILT-004** MUST: All public API ViewModels MUST extend BaseViewModel and inject dependencies through constructor parameters annotated with @Inject. +- **R-HILT-005** SHOULD: Repository or manager layer components SHOULD be used for Intent processing logic rather than embedding Android framework calls directly in ViewModel. +- **R-HILT-006** SHOULD: Unit tests for ViewModels SHOULD use Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies. + +### Verify + +```bash +# Verify @HiltViewModel annotation on public API boundary ViewModels +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l + +# Verify sealed action types are defined +grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l + +# Verify public API ViewModels extend BaseViewModel and use @HiltViewModel +find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l +``` + +**Accept when:** +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters +- No public API boundary ViewModels lack @HiltViewModel annotation + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for public API boundary ViewModels. Violations block CI pipeline and require architecture team approval for exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-inject-savedstatehandle-66c4.md b/.actual/rules/cross-cutting-viewmodels-inject-savedstatehandle-66c4.md new file mode 100644 index 00000000000..3476c399eed --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-inject-savedstatehandle-66c4.md @@ -0,0 +1,42 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Inject Savedstatehandle + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the app module, including UI state management for authentication flows, application-level state coordination, and state objects representing dialog states, loading states, and error states. + +### Rules + +- **R-HILT-VM-001** MAY: ViewModels MAY inject SavedStateHandle to access navigation arguments and persist state across process death. +- **R-HILT-VM-002** MUST: All ViewModel classes MUST be annotated with @HiltViewModel and use constructor injection for dependencies. +- **R-HILT-VM-003** MUST: State MUST be defined as immutable Parcelable data classes with all properties declared as val. +- **R-HILT-VM-004** MUST: All state mutations MUST use mutableStateFlow.update { it.copy(property = newValue) } pattern to ensure atomicity and prevent direct value assignments. +- **R-HILT-VM-005** MUST: Asynchronous operations MUST execute within viewModelScope for proper lifecycle management and coroutine cancellation. +- **R-HILT-VM-006** MUST: State exposed to UI MUST be as StateFlow using stateIn or asStateFlow to prevent external mutations. +- **R-HILT-VM-007** SHOULD: Complex state transitions SHOULD use sealed classes for variant states such as dialogs and loading states. +- **R-HILT-VM-008** SHOULD: ViewModels SHOULD initialize MutableStateFlow with initial state from SavedStateHandle or default values. + +### Verify + +```bash +# Verify @HiltViewModel annotation presence +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Verify mutableStateFlow.update pattern usage +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Verify Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Verify viewModelScope usage +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management +- State exposed to UI is declared as StateFlow, not MutableStateFlow +- No direct assignments to mutableStateFlow.value property are present + + +Claude Code MUST NOT skip or defer verification of these rules. All ViewModel implementations MUST comply with R-HILT-VM-002, R-HILT-VM-003, R-HILT-VM-004, R-HILT-VM-005, and R-HILT-VM-006 before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-public-boundaries-67b3.md b/.actual/rules/cross-cutting-viewmodels-public-boundaries-67b3.md new file mode 100644 index 00000000000..9bfe3b1bf29 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-public-boundaries-67b3.md @@ -0,0 +1,34 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Public Boundaries + +These rules are ALWAYS ACTIVE for all Android ViewModels serving as public API boundaries for system integrations, including credential provider APIs, authentication callback Intents, and autofill service interactions. + +### Rules + +- **R-HILT-001** MUST: ViewModels at public API boundaries MUST extend BaseViewModel to ensure consistent lifecycle and state management. +- **R-HILT-002** MUST: All public API boundary ViewModels MUST be annotated with @HiltViewModel for Android-aware dependency injection. +- **R-HILT-003** MUST: Constructor parameters in @HiltViewModel-annotated ViewModels MUST be annotated with @Inject. +- **R-HILT-004** MUST: Public API boundary ViewModels MUST define sealed action types for type-safe Intent-based contracts. +- **R-HILT-005** SHOULD: Intent processing logic SHOULD be delegated to repository or manager layer components rather than embedded directly in ViewModel. + +### Verify + +```bash +# Verify @HiltViewModel annotation on public API boundary ViewModels +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l + +# Verify sealed action types are defined +grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l + +# Verify public API ViewModels extend BaseViewModel and use @HiltViewModel +find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l +``` + +**Accept when:** +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters annotated with @Inject +- Intent processing logic is delegated to repository or manager layer components + + +Clause Code MUST NOT skip or defer verification. All public API boundary ViewModels must pass the verify commands before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-requiring-dependency-bc78.md b/.actual/rules/cross-cutting-viewmodels-requiring-dependency-bc78.md new file mode 100644 index 00000000000..4e0a6fab7d7 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-requiring-dependency-bc78.md @@ -0,0 +1,36 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Viewmodels Requiring Dependency + +These rules are ALWAYS ACTIVE for all Android Activities, ViewModels, and Application classes requiring dependency injection across authentication, autofill, and credential provider flows. + +### Rules + +- **R-HILT-001** MUST: All ViewModels requiring dependency injection MUST be annotated with @HiltViewModel and use constructor injection. +- **R-HILT-002** MUST: All Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint. +- **R-HILT-003** MUST: The Application class MUST use @Inject for application-scoped dependencies. +- **R-HILT-004** SHOULD: Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint. +- **R-HILT-005** SHOULD: Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle. +- **R-HILT-006** SHOULD: Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types). + +### Verify + +```bash +# Count @AndroidEntryPoint annotations on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Count @HiltViewModel annotations on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify Application class uses @Inject +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence +- Annotation processing completes successfully in CI build pipeline + + +Claude Code MUST NOT skip or defer verification. All new Activities and ViewModels requiring dependency injection MUST be validated against these rules before approval. Build failures from annotation processing errors MUST be resolved before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-use-constructor-14cc.md b/.actual/rules/cross-cutting-viewmodels-use-constructor-14cc.md new file mode 100644 index 00000000000..88c708acde7 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-use-constructor-14cc.md @@ -0,0 +1,40 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Viewmodels Use Constructor + +These rules are ALWAYS ACTIVE for all Android Activity subclasses, ViewModel implementations, Application classes, Repository and Manager classes, and feature modules (authentication, autofill, credential provider) that require dependency injection. + +### Rules + +- **R-HILT-001** MUST: ViewModels MUST use constructor injection for all dependencies to maintain testability. +- **R-HILT-002** MUST: All Activity classes MUST be annotated with @AndroidEntryPoint. +- **R-HILT-003** MUST: All ViewModel classes MUST be annotated with @HiltViewModel. +- **R-HILT-004** MUST: The Application class MUST be annotated with @HiltAndroidApp to initialize the Hilt dependency graph. +- **R-HILT-005** MUST: Activities MUST use androidx.activity.viewModels() delegate to obtain Hilt-injected ViewModels with proper scoping. +- **R-HILT-006** SHOULD: Dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) SHOULD be documented in module provider methods. + +### Verify + +```bash +# Verify @AndroidEntryPoint annotations on Activity classes +grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l + +# Verify @HiltViewModel annotations on ViewModel classes +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Verify @Inject constructor injection usage +grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l + +# Verify Hilt is configured in build +./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' +``` + +**Accept when:** +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle +- No Activity classes use field injection (@Inject on lateinit var) instead of constructor injection +- No ViewModel classes instantiate dependencies manually or use service locators + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for code review and CI/CD pipeline validation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-use-constructor-b4ab.md b/.actual/rules/cross-cutting-viewmodels-use-constructor-b4ab.md new file mode 100644 index 00000000000..60648911ab2 --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-use-constructor-b4ab.md @@ -0,0 +1,38 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Viewmodels Use Constructor + +These rules are ALWAYS ACTIVE for all Android Activities, ViewModels, and Application classes requiring dependency injection across authentication, autofill, and credential provider flows. + +### Rules + +- **R-HILT-001** MUST: All Activity classes requiring dependency injection SHALL be annotated with @AndroidEntryPoint. +- **R-HILT-002** MUST: All ViewModel classes requiring dependency injection SHALL be annotated with @HiltViewModel. +- **R-HILT-003** MUST: The Application class SHALL use @Inject for application-scoped dependencies. +- **R-HILT-004** SHOULD: ViewModels SHOULD use constructor injection rather than field injection for testability. +- **R-HILT-005** SHOULD: Hilt modules SHOULD be created for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types). +- **R-HILT-006** SHOULD: Hilt scoping guidelines SHOULD be followed: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle. + +### Verify + +```bash +# Verify @AndroidEntryPoint annotations on Activity classes +grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l + +# Verify @HiltViewModel annotations on ViewModel classes +grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l + +# Verify @Inject usage in Application class +grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt +``` + +**Accept when:** +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence +- No Activities or ViewModels with constructor parameters lack required Hilt annotations +- Annotation processing completes successfully in CI build pipeline +- No improper scope usage detected (e.g., ActivityScoped dependencies in ViewModels) + + +Claude Code MUST NOT skip or defer verification. All verification commands MUST execute successfully before accepting changes to Android Activities, ViewModels, or Application classes. Code review MUST enforce Hilt annotations on new components. Build failures from annotation processing errors MUST be resolved before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-viewmodels-use-mutablestateflow-8c03.md b/.actual/rules/cross-cutting-viewmodels-use-mutablestateflow-8c03.md new file mode 100644 index 00000000000..94aef57f10e --- /dev/null +++ b/.actual/rules/cross-cutting-viewmodels-use-mutablestateflow-8c03.md @@ -0,0 +1,39 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Use Mutablestateflow + +These rules are ALWAYS ACTIVE for all Android ViewModel implementations in the codebase, specifically targeting UI state management for authentication flows, application-level state coordination, and state objects representing dialog states, loading states, and error states. + +### Rules + +- **R-HILT-VM-001** MUST: ViewModels MUST use MutableStateFlow to hold UI state and expose it as immutable StateFlow to UI consumers. +- **R-HILT-VM-002** MUST: Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor. +- **R-HILT-VM-003** MUST: Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs. +- **R-HILT-VM-004** MUST: Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity. +- **R-HILT-VM-005** MUST: Launch coroutines within viewModelScope for asynchronous operations; update state in response to results. +- **R-HILT-VM-006** MUST: Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations. +- **R-HILT-VM-007** SHOULD: Implement state classes with Parcelable interface for restoration support across process death. + +### Verify + +```bash +# Count @HiltViewModel annotations in ViewModel files +grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count mutableStateFlow.update usages +grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +# Count Parcelable state classes +grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l + +# Count viewModelScope usages +grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +``` + +**Accept when:** +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + + +Clause Code MUST NOT skip or defer verification. Violations detected by static analysis rules or code review must be addressed before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-when-type-discriminators-5dab.md b/.actual/rules/cross-cutting-when-type-discriminators-5dab.md new file mode 100644 index 00000000000..93f684ed9b7 --- /dev/null +++ b/.actual/rules/cross-cutting-when-type-discriminators-5dab.md @@ -0,0 +1,30 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: When Type Discriminators + +These rules are ALWAYS ACTIVE for custom kotlinx.serialization serializers for domain models, extension functions converting between domain models and SDK types, JSON encoding/decoding at service and module boundaries, and versioned serialization formats using type discriminators. + +### Rules + +- **R-SERIAL-001** MUST: When using type discriminators for versioned schemas, tests MUST verify the discriminator field value for each version. + +### Verify + +```bash +# Count @Test methods in serializer test files +grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l + +# Count buildJsonObject + assertEquals patterns in serialization tests +grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l + +# Find test files using kotlinx.serialization +find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' +``` + +**Accept when:** +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + + +Claude Code MUST NOT skip or defer verification of type discriminator field values in serialization tests. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-xml-parsing-operations-dd22.md b/.actual/rules/cross-cutting-xml-parsing-operations-dd22.md new file mode 100644 index 00000000000..652cfef3687 --- /dev/null +++ b/.actual/rules/cross-cutting-xml-parsing-operations-dd22.md @@ -0,0 +1,40 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Xml Parsing Operations + +These rules are ALWAYS ACTIVE for all XML parsing operations, tool handlers in android-device-server, GitHub automation scripts processing external inputs, and public API contracts exposed through ToolDefinition interfaces. + +### Rules + +- **R-XML-001** MUST: XML parsing operations MUST use fast-xml-parser with parser.parse() to validate structure before extracting UI hierarchy or element data. +- **R-XML-002** MUST: All tool handlers in android-device-server (capture.ts, tap-at.ts) MUST define zod schemas with explicit type constraints for all required and optional parameters before processing inputs. +- **R-XML-003** MUST: JSON configuration loading in GitHub automation scripts MUST include exception handling and validation of required fields before accessing. +- **R-XML-004** SHOULD: Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers. +- **R-XML-005** SHOULD: Configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements. +- **R-XML-006** MAY: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally. + +### Verify + +```bash +# Count zod schema definitions in tool handlers +grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l + +# Count fast-xml-parser usage in parsers +grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l + +# Count json.load calls in GitHub scripts +grep -r "json\.load(" .github/scripts/ | wc -l + +# Run validation tests +npm test -- --testPathPattern=validation +``` + +**Accept when:** +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML +- No unvalidated external inputs are detected in TypeScript modules via static analysis +- Integration tests verify validation error responses for invalid inputs across all public APIs + + +Clause Code MUST NOT skip or defer verification. All XML parsing operations and external input handling MUST conform to these rules before merge. Code review checklist MUST require zod schema definitions for new API endpoints. Pull requests introducing new API endpoints without input validation schemas are blocked. Security team review and approval is required for any API endpoint processing external input without schema validation. + \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..2498ac0c735 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,55 @@ + +# Project ADRs + +This project's conventions are encoded as ADRs under `.actual/rules/`. **The ADRs ARE the pattern.** Follow them verbatim instead of reading existing implementations to figure out how to do something. + +> **Note:** this directive is calibrated for one-shot tasks (a single discrete feature). For multi-task interactive sessions, consult the ADRs for each task transition rather than holding to the per-session caps below. + +## Workflow (follow in order) + +1. **Identify topic.** Match the files you'll edit against the path-glob table below. Pick the 1-3 topics that match. Do not pre-emptively pick "related" topics; pick only what the file paths actually match. + +2. **Select ADRs by filename — the filename is the index.** Run `ls .actual/rules/`. Each filename is `--.md`; the `` (middle segment) names the ADR's specific concern — e.g., `database-schema-defined`, `zod-input-validation`, `cache-key-format`. + + **Scan ALL filenames first, then pick only the ones whose aspect-slug directly names a noun or verb in your task.** Select by filename; never read a body to decide relevance. **Hard cap: read at most 5 ADR files total.** If more than 5 look relevant, you are over-matching — keep the 5 most specific. + + **If the path-glob table below is a single `**/*` → `cross-cutting-` row** (one big bucket, no per-area topics), this filename scan is your ONLY filter. Do **not** read the bucket exhaustively — treat the filenames as a menu, match aspect-slugs to your task, read ≤5, and ignore the rest. Reading every ADR in the bucket is the exact failure this directive exists to prevent. + +3. **Locate insertion points (one read per file, max 3 files).** You may read source files ONLY to (a) find where to add code (which directory, which barrel export to update) or (b) look up an exact identifier you must import. **Do not read source files as pattern examples — the ADRs already encode the pattern.** If you find yourself reading a file because "I want to see how X is done elsewhere," stop. The ADR you already read tells you how. + +4. **Implement.** Write the code following the rule statements verbatim. If two ADRs seem to conflict, follow the more specific one (longer topic prefix wins). + +5. **Verify after implementing.** Only after the code is written, re-read the `verify_commands` or `accept_criteria` sections of the ADRs you applied and check your work against them. Run the verify commands if any. + +## Anti-patterns to avoid + +- Reading the first N rules alphabetically because they're cheap. Filter by aspect-slug first, then read only the relevant ones. +- Reading >5 ADR files for a single feature. If you're tempted, you're over-scoping the topic match. +- Reading the entire `cross-cutting-` bucket because "every rule is always active." Selection is by filename (step 2); you apply the ≤5 you selected, not all of them. +- Reading existing similar features to "see the pattern" — the ADRs encode the pattern. Trust them. +- Re-reading the same ADR multiple times. Cache it mentally. +- Continuing to browse the codebase after step 3. By step 4 you should be writing, not reading. + +Each rule file at `.actual/rules/--.md` contains the full ADR with rule statements, verify commands, and accept criteria. + +## Verification Protocol + +These rules are ALWAYS ACTIVE. Apply every rule **from the ADRs you selected in step 2** that governs the files you touch — to all code generation, modification, and review. "Always active" does **not** mean read every ADR: you apply the handful you selected by filename, within the read cap above. + +Every rule follows a **Verify → Fix → Repeat** loop. After generating or modifying code for any rule you MUST: + +1. **RUN** the rule's `### Verify` command(s). +2. **CAPTURE** the full output (stdout + stderr). +3. **EVALUATE** the output against the rule's **Accept when** criteria. +4. **IF FAILING:** diagnose the root cause, apply a fix, and re-run from step 1. +5. **IF PASSING:** keep the passing output as evidence before moving on. +6. **MAX ITERATIONS:** 5 attempts per rule. If still failing after 5 attempts, STOP and report the failure with all captured output. + +Compliance is not optional. Do not skip verification, assume correctness, or defer it to a later task. Every change to a governed area must be accompanied by a passing verification run. + +## Path glob → topic + +| You're editing | Topic prefix | +|---|---| +| `**/*` | `cross-cutting-` _(195 ADRs)_ | + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000000..2498ac0c735 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ + +# Project ADRs + +This project's conventions are encoded as ADRs under `.actual/rules/`. **The ADRs ARE the pattern.** Follow them verbatim instead of reading existing implementations to figure out how to do something. + +> **Note:** this directive is calibrated for one-shot tasks (a single discrete feature). For multi-task interactive sessions, consult the ADRs for each task transition rather than holding to the per-session caps below. + +## Workflow (follow in order) + +1. **Identify topic.** Match the files you'll edit against the path-glob table below. Pick the 1-3 topics that match. Do not pre-emptively pick "related" topics; pick only what the file paths actually match. + +2. **Select ADRs by filename — the filename is the index.** Run `ls .actual/rules/`. Each filename is `--.md`; the `` (middle segment) names the ADR's specific concern — e.g., `database-schema-defined`, `zod-input-validation`, `cache-key-format`. + + **Scan ALL filenames first, then pick only the ones whose aspect-slug directly names a noun or verb in your task.** Select by filename; never read a body to decide relevance. **Hard cap: read at most 5 ADR files total.** If more than 5 look relevant, you are over-matching — keep the 5 most specific. + + **If the path-glob table below is a single `**/*` → `cross-cutting-` row** (one big bucket, no per-area topics), this filename scan is your ONLY filter. Do **not** read the bucket exhaustively — treat the filenames as a menu, match aspect-slugs to your task, read ≤5, and ignore the rest. Reading every ADR in the bucket is the exact failure this directive exists to prevent. + +3. **Locate insertion points (one read per file, max 3 files).** You may read source files ONLY to (a) find where to add code (which directory, which barrel export to update) or (b) look up an exact identifier you must import. **Do not read source files as pattern examples — the ADRs already encode the pattern.** If you find yourself reading a file because "I want to see how X is done elsewhere," stop. The ADR you already read tells you how. + +4. **Implement.** Write the code following the rule statements verbatim. If two ADRs seem to conflict, follow the more specific one (longer topic prefix wins). + +5. **Verify after implementing.** Only after the code is written, re-read the `verify_commands` or `accept_criteria` sections of the ADRs you applied and check your work against them. Run the verify commands if any. + +## Anti-patterns to avoid + +- Reading the first N rules alphabetically because they're cheap. Filter by aspect-slug first, then read only the relevant ones. +- Reading >5 ADR files for a single feature. If you're tempted, you're over-scoping the topic match. +- Reading the entire `cross-cutting-` bucket because "every rule is always active." Selection is by filename (step 2); you apply the ≤5 you selected, not all of them. +- Reading existing similar features to "see the pattern" — the ADRs encode the pattern. Trust them. +- Re-reading the same ADR multiple times. Cache it mentally. +- Continuing to browse the codebase after step 3. By step 4 you should be writing, not reading. + +Each rule file at `.actual/rules/--.md` contains the full ADR with rule statements, verify commands, and accept criteria. + +## Verification Protocol + +These rules are ALWAYS ACTIVE. Apply every rule **from the ADRs you selected in step 2** that governs the files you touch — to all code generation, modification, and review. "Always active" does **not** mean read every ADR: you apply the handful you selected by filename, within the read cap above. + +Every rule follows a **Verify → Fix → Repeat** loop. After generating or modifying code for any rule you MUST: + +1. **RUN** the rule's `### Verify` command(s). +2. **CAPTURE** the full output (stdout + stderr). +3. **EVALUATE** the output against the rule's **Accept when** criteria. +4. **IF FAILING:** diagnose the root cause, apply a fix, and re-run from step 1. +5. **IF PASSING:** keep the passing output as evidence before moving on. +6. **MAX ITERATIONS:** 5 attempts per rule. If still failing after 5 attempts, STOP and report the failure with all captured output. + +Compliance is not optional. Do not skip verification, assume correctness, or defer it to a later task. Every change to a governed area must be accompanied by a passing verification run. + +## Path glob → topic + +| You're editing | Topic prefix | +|---|---| +| `**/*` | `cross-cutting-` _(195 ADRs)_ | + diff --git a/docs/adr/02ab6269-efc6-43d8-8dab-11f6fad6e18c-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-methods-include.md b/docs/adr/02ab6269-efc6-43d8-8dab-11f6fad6e18c-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-methods-include.md new file mode 100644 index 00000000000..6f720b325ec --- /dev/null +++ b/docs/adr/02ab6269-efc6-43d8-8dab-11f6fad6e18c-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-methods-include.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Methods Include + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. SHOULD: Test methods SHOULD include docstrings that clearly describe the contract being tested + +## Policy Block + +- SHOULD Test methods SHOULD include docstrings that clearly describe the contract being tested + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/0482e3b2-d96e-4410-a1b3-bfaff3c52773-adopt-async-handler-pattern-for-tool-operations-handler-functions-coordinate.md b/docs/adr/0482e3b2-d96e-4410-a1b3-bfaff3c52773-adopt-async-handler-pattern-for-tool-operations-handler-functions-coordinate.md new file mode 100644 index 00000000000..9c3bcec2600 --- /dev/null +++ b/docs/adr/0482e3b2-d96e-4410-a1b3-bfaff3c52773-adopt-async-handler-pattern-for-tool-operations-handler-functions-coordinate.md @@ -0,0 +1,120 @@ +# Adopt Async Handler Pattern for Tool Operations: Handler Functions Coordinate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the android-device-server MCP service. + +## Context + +- The android-device-server MCP service implements multiple tool operations (capture, tap-at, find-element-pipeline) that interact with external Android Debug Bridge (adb) processes and file system operations +- Tool operations require coordination of asynchronous I/O including process execution, file reads/writes, and validation steps that cannot block the event loop +- Each tool exports a handler function that serves as the primary entry point for tool invocation, establishing a consistent interface pattern across the codebase +- The codebase uses Zod for input validation schemas and node:path/node:fs for file system operations, requiring async coordination between validation and execution phases + +## Problem Statement + +Tool operations in the android-device-server require a consistent concurrency model that coordinates asynchronous validation, external process execution, and file system operations without blocking the Node.js event loop, while maintaining a uniform interface pattern across all tool implementations. + +## Decision + +1. MUST: Handler functions MUST coordinate asynchronous operations including validation, adb process execution, and file system I/O using async/await patterns + +## Policy Block + +- MUST Handler functions MUST coordinate asynchronous operations including validation, adb process execution, and file system I/O using async/await patterns + +In scope: +- All tool implementations in the android-device-server/src/tools directory +- Handler functions that coordinate adb process execution +- Operations involving file system reads/writes via node:fs +- Tool entry points exported for MCP service consumption + +Out of scope: +- Utility functions that do not serve as tool entry points +- Synchronous helper functions for data transformation +- Type definitions and interface declarations +- Test harness and mock implementations + +Exceptions: +- EXC-001: Pure computational functions that perform synchronous transformations without I/O + +## Rationale + +- The evidence shows consistent use of async handler functions (capture, tapAt, findElementWithObstruction) across 3 tool implementations, indicating an established pattern for coordinating asynchronous operations +- All detected tools import adb utilities and validation modules, requiring async coordination between validation, process execution, and result handling +- The handler pattern provides a uniform interface for tool invocation while encapsulating the complexity of async I/O coordination with external processes and file systems +- Using async/await patterns prevents event loop blocking and enables proper error propagation in the Node.js runtime environment + +## Consequences + +Positive: +- Consistent interface pattern across all tool implementations improves code maintainability and developer onboarding +- Non-blocking async operations ensure the MCP service remains responsive during long-running adb operations +- Separation of validation and execution phases enables early input rejection before expensive I/O operations +- Async/await syntax provides clear error handling and control flow compared to callback-based patterns + +Negative: +- Async handler pattern adds complexity compared to synchronous implementations for simple operations +- Requires developers to understand Promise semantics and async/await error handling +- Potential for unhandled promise rejections if error handling is not properly implemented +- Debugging async call stacks can be more challenging than synchronous execution flows + +## Alternatives + +- Synchronous handler functions with blocking I/O operations (rejected) + Rejected because: Blocking I/O would freeze the Node.js event loop during adb process execution and file operations, making the service unresponsive to concurrent requests + When valid: Only appropriate for pure computational functions without I/O dependencies +- Callback-based asynchronous pattern using Node.js callback conventions (rejected) + Rejected because: Callback patterns lead to nested callback hell and more complex error handling compared to async/await syntax available in modern Node.js + When valid: Legacy codebases or when targeting very old Node.js versions without async/await support +- Event emitter pattern for tool operations (rejected) + Rejected because: Event emitters add unnecessary complexity for request-response tool operations that have clear start and end points + When valid: Appropriate for streaming operations or long-running processes with multiple intermediate events + +## Risks + +- Unhandled promise rejections in handler functions could crash the Node.js process or leave operations in inconsistent states + Mitigation: Implement comprehensive try-catch blocks in all async handlers and configure Node.js to log unhandled rejections. Add integration tests that verify error handling paths. + Owner: Engineering team +- Long-running adb operations could accumulate pending promises and exhaust memory if not properly managed + Mitigation: Implement timeouts for all adb operations and add monitoring for pending promise counts. Consider implementing operation queuing with concurrency limits. + Owner: Engineering team +- Inconsistent error handling patterns across handlers could lead to unpredictable failure modes + Mitigation: Establish standard error handling patterns and document them. Create shared error handling utilities that all handlers can use. + Owner: Engineering team + +## Implementation Notes + +- All new tool implementations should follow the pattern: export an async function that accepts validated parameters and returns a Promise of the operation result +- Use Zod schemas defined at module level for input validation, and validate before entering the async handler logic +- Import adb utilities and file system operations from their respective modules (../adb/adb.js, node:fs, node:path) and await their results +- Ensure all async handlers have proper error handling with try-catch blocks and meaningful error messages that include context about the failed operation + +## Continuation Context + + +Verify commands: +- grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + +## Enforcement + +- Verified by: Code review checklist requiring async handler pattern for new tools +- Verified by: ESLint rules detecting synchronous I/O operations in tool handlers +- Verified by: Integration tests verifying non-blocking behavior under concurrent load +- Violation handling: Code review rejection for synchronous I/O in handler functions +- Violation handling: CI pipeline failure on ESLint violations for blocking operations +- Violation handling: Automated comments on PRs identifying missing async/await patterns +- Exception process: Document exception rationale in ADR amendment or inline code comments +- Exception process: Obtain tech lead approval for synchronous operations in tool handlers +- Exception process: Add exception to ESLint configuration with justification comment \ No newline at end of file diff --git a/docs/adr/0705eaa1-53bb-4b7d-85c5-442ae28e26ac-enforce-schema-based-input-validation-for-public-api-endpoints-use-custom-validation.md b/docs/adr/0705eaa1-53bb-4b7d-85c5-442ae28e26ac-enforce-schema-based-input-validation-for-public-api-endpoints-use-custom-validation.md new file mode 100644 index 00000000000..1872720b50e --- /dev/null +++ b/docs/adr/0705eaa1-53bb-4b7d-85c5-442ae28e26ac-enforce-schema-based-input-validation-for-public-api-endpoints-use-custom-validation.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Use Custom Validation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. MAY: APIs MAY use custom validation functions for complex business rules that cannot be expressed through declarative schema constraints + +## Policy Block + +- MAY APIs MAY use custom validation functions for complex business rules that cannot be expressed through declarative schema constraints + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/09073977-2366-4777-9cad-69ed4f5d103e-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-use-subprocess.md b/docs/adr/09073977-2366-4777-9cad-69ed4f5d103e-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-use-subprocess.md new file mode 100644 index 00000000000..694f5d0070f --- /dev/null +++ b/docs/adr/09073977-2366-4777-9cad-69ed4f5d103e-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-use-subprocess.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Scripts Use Subprocess + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. MAY: Scripts MAY use subprocess module to invoke git or GitHub CLI commands for retrieving PR metadata and file changes + +## Policy Block + +- MAY Scripts MAY use subprocess module to invoke git or GitHub CLI commands for retrieving PR metadata and file changes + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/0a858504-83de-443b-b3d8-56bb1f18bb5a-standardize-console-error-and-response-error-for-error-logging-in-libraries-typescript-libraries-use.md b/docs/adr/0a858504-83de-443b-b3d8-56bb1f18bb5a-standardize-console-error-and-response-error-for-error-logging-in-libraries-typescript-libraries-use.md new file mode 100644 index 00000000000..8f9fc0a378e --- /dev/null +++ b/docs/adr/0a858504-83de-443b-b3d8-56bb1f18bb5a-standardize-console-error-and-response-error-for-error-logging-in-libraries-typescript-libraries-use.md @@ -0,0 +1,117 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Typescript Libraries Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Library modules in both TypeScript (android-device-server) and Kotlin (bitwarden network layer) implement error logging using platform-native error reporting mechanisms +- The TypeScript implementation uses console.error for tool errors and fatal errors in an MCP server context, while the Kotlin implementation uses Response.error with HTTP status codes and JSON-formatted error messages +- Both implementations integrate error logging within core library functionality, suggesting a cross-platform pattern for observable error handling in modular architectures +- The pattern appears in libraries that serve as integration points: an Android device MCP server and a network layer for API communication + +## Problem Statement + +Library modules require consistent, observable error logging mechanisms that integrate with their respective runtime environments (Node.js console for TypeScript, Retrofit Response for Kotlin) to enable debugging, monitoring, and error propagation without introducing external logging framework dependencies. + +## Decision + +1. SHOULD: TypeScript libraries SHOULD use console.error with descriptive prefixes (e.g., 'Tool error (${name}):', 'Fatal error:') to distinguish error severity and context + +## Policy Block + +- SHOULD TypeScript libraries SHOULD use console.error with descriptive prefixes (e.g., 'Tool error (${name}):', 'Fatal error:') to distinguish error severity and context + +In scope: +- TypeScript libraries running in Node.js environments with console API access +- Kotlin libraries using Retrofit for HTTP client functionality +- Library modules designed for reuse across multiple applications or services +- Error handling code paths within library boundaries + +Out of scope: +- Application-level logging infrastructure and aggregation systems +- Structured logging frameworks (Winston, Log4j, SLF4J) used by consuming applications +- Production monitoring and alerting systems external to library code +- Log persistence, rotation, or archival mechanisms + +Exceptions: +- EXC-001: Library is explicitly designed as a logging abstraction or wrapper (e.g., a logging facade library) +- EXC-002: Library operates in an environment without platform-native error logging (embedded systems, constrained runtimes) + +## Rationale + +- Platform-native error logging mechanisms (console.error, Response.error) are universally available in their respective runtime environments, eliminating external dependencies and reducing library footprint +- The pattern observed across TypeScript and Kotlin implementations demonstrates a cross-platform architectural principle: libraries should use runtime-provided error reporting rather than introducing framework coupling +- Using platform-native mechanisms enables library consumers to intercept, redirect, or enhance error logging through standard runtime hooks (console redirection, Retrofit interceptors) without modifying library code +- The evidence shows consistent integration of error logging with core library operations (tool execution, HTTP response construction), indicating error observability is treated as a first-class concern in library design + +## Consequences + +Positive: +- Reduced library dependency footprint by avoiding external logging framework dependencies +- Improved library portability across different application contexts and deployment environments +- Simplified library testing through standard console/response mocking mechanisms +- Enhanced consumer flexibility to integrate library error logging with application-specific monitoring infrastructure + +Negative: +- Limited structured logging capabilities compared to dedicated logging frameworks (no log levels, structured fields, or filtering) +- Potential inconsistency in error log format across different libraries and platforms +- Reduced observability features such as automatic context propagation, correlation IDs, or distributed tracing integration +- Console.error output may be difficult to parse or aggregate in production monitoring systems without additional tooling + +## Alternatives + +- Adopt a lightweight, cross-platform logging abstraction library (e.g., pino for TypeScript, SLF4J for Kotlin) as a standard dependency (rejected) + Rejected because: Introduces external dependency and version management complexity; conflicts with the observed pattern of using platform-native mechanisms; reduces library portability + When valid: When libraries require structured logging with log levels, filtering, and production-grade observability features that justify the dependency cost +- Implement custom logging abstraction within each library with pluggable backends (rejected) + Rejected because: Increases library code complexity and maintenance burden; duplicates logging abstraction logic across libraries; evidence shows preference for simple, direct error reporting + When valid: When building a library ecosystem with shared logging requirements and centralized logging infrastructure management +- Provide optional logging callback parameters for all error-prone operations (deferred) + Rejected because: Not observed in current evidence; would require API design changes across library interfaces + When valid: As an enhancement to enable custom error handling while maintaining platform-native defaults (see R-20-006) + +## Risks + +- Inconsistent error log formats across libraries make centralized monitoring and alerting difficult to implement + Mitigation: Establish error message format conventions (e.g., prefix patterns, JSON structure) documented in library development guidelines; provide examples of log parsing patterns for common monitoring tools + Owner: Engineering team, library maintainers +- Platform-native error logging may not provide sufficient detail for debugging complex library interactions in production + Mitigation: Ensure error messages include actionable context (operation name, input parameters, error codes); document error scenarios and troubleshooting steps in library documentation; consider optional verbose logging modes + Owner: Engineering team +- Console.error output in high-throughput scenarios may impact performance or overwhelm log aggregation systems + Mitigation: Implement error rate limiting or sampling for repetitive errors; document expected error logging volume in library performance characteristics; provide guidance on console redirection for production environments + Owner: Engineering team, SRE team + +## Implementation Notes + +- For TypeScript libraries, use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin network libraries using Retrofit, construct Response.error with appropriate HTTP status codes (e.g., HTTP_CODE_BAD_REQUEST) and JSON-formatted error messages using ResponseBody.Companion.toResponseBody +- Include sufficient context in error messages to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes +- Document expected error log output format and examples in library README to help consumers implement log parsing and monitoring + +## Continuation Context + + +Verify commands: +- grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" +- grep -r "Response\.error" --include="*.kt" src/ | head -20 +- grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l + +Accept when: +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + +## Enforcement + +- Verified by: Code review checklist verifying use of platform-native error logging mechanisms +- Verified by: Dependency analysis in CI pipeline flagging external logging framework dependencies in library modules +- Verified by: Grep-based verification commands checking for console.error and Response.error patterns in library code +- Violation handling: Code review feedback requesting removal of external logging framework dependencies and migration to platform-native mechanisms +- Violation handling: CI pipeline warnings when external logging dependencies are detected in library package manifests +- Violation handling: Architecture review required for libraries that cannot use platform-native error logging due to runtime constraints +- Exception process: Submit exception request documenting runtime environment constraints or logging requirements that cannot be met with platform-native mechanisms +- Exception process: Technical lead or architecture review approval required for exception +- Exception process: Document approved exceptions in library README with justification and alternative error reporting mechanism details \ No newline at end of file diff --git a/docs/adr/0acc83c8-3c34-457a-9f19-eb7e32cc5e62-enforce-schema-based-input-validation-for-public-api-endpoints-public-endpoints-that.md b/docs/adr/0acc83c8-3c34-457a-9f19-eb7e32cc5e62-enforce-schema-based-input-validation-for-public-api-endpoints-public-endpoints-that.md new file mode 100644 index 00000000000..b9a25ff339f --- /dev/null +++ b/docs/adr/0acc83c8-3c34-457a-9f19-eb7e32cc5e62-enforce-schema-based-input-validation-for-public-api-endpoints-public-endpoints-that.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Public Endpoints That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. MUST: All public API endpoints that accept external input MUST validate input using a schema validation library (zod for TypeScript, json.load with schema validation for Python) before processing + +## Policy Block + +- MUST All public API endpoints that accept external input MUST validate input using a schema validation library (zod for TypeScript, json.load with schema validation for Python) before processing + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/0c4ddb3c-4f75-4172-a5dd-e6815bf1c6f1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-utilities-imported.md b/docs/adr/0c4ddb3c-4f75-4172-a5dd-e6815bf1c6f1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-utilities-imported.md new file mode 100644 index 00000000000..de373f14c02 --- /dev/null +++ b/docs/adr/0c4ddb3c-4f75-4172-a5dd-e6815bf1c6f1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-utilities-imported.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Validation Utilities Imported + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. SHOULD: Validation utilities SHOULD be imported from '../utils/validation.js' to promote reuse across tool implementations + +## Policy Block + +- SHOULD Validation utilities SHOULD be imported from '../utils/validation.js' to promote reuse across tool implementations + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/0deb24db-6744-474e-86e4-0084c8180782-standardize-kotlinx-serialization-json-testing-with-type-discriminators-tests-use-mock.md b/docs/adr/0deb24db-6744-474e-86e4-0084c8180782-standardize-kotlinx-serialization-json-testing-with-type-discriminators-tests-use-mock.md new file mode 100644 index 00000000000..3490674dd6b --- /dev/null +++ b/docs/adr/0deb24db-6744-474e-86e4-0084c8180782-standardize-kotlinx-serialization-json-testing-with-type-discriminators-tests-use-mock.md @@ -0,0 +1,116 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Tests Use Mock + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests validate JSON encoding/decoding behavior at service boundaries where data crosses module or API boundaries +- The codebase uses kotlinx.serialization for JSON serialization with custom serializers for domain models like WrappedAccountCryptographicState +- Type discriminators (e.g., 'v1', 'v2') enable versioned serialization formats to support backward compatibility and schema evolution +- Tests use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings +- The pattern appears in cryptographic state serialization and policy view conversion, indicating cross-cutting serialization concerns + +## Problem Statement + +Service boundaries require reliable serialization contracts that can evolve over time without breaking existing clients. Without standardized testing of JSON serialization including type discriminators and property mappings, schema changes may introduce silent data corruption or deserialization failures at runtime. + +## Decision + +1. MAY: Tests MAY use mock factory functions (e.g., createMockPolicy) to generate test data consistently + +## Policy Block + +- MAY Tests MAY use mock factory functions (e.g., createMockPolicy) to generate test data consistently + +In scope: +- Custom kotlinx.serialization serializers for domain models +- Extension functions converting between domain models and SDK types +- JSON encoding/decoding at service and module boundaries +- Versioned serialization formats using type discriminators + +Out of scope: +- Internal data transformations that do not cross serialization boundaries +- Third-party library serializers without custom logic +- Binary serialization formats +- Database entity mappings + +## Rationale + +- The evidence shows consistent use of kotlinx.serialization.json.buildJsonObject and assertEquals patterns across serialization tests, indicating an established testing approach +- Type discriminators ('v1', 'v2') in WrappedAccountCryptographicState tests demonstrate versioning requirements at cryptographic state boundaries +- Tests for toSdkPolicyViews extension function show validation of conversion logic between network models and SDK policy views +- The pattern appears in both data layer (cryptographic state) and vault repository (policy conversion), suggesting cross-cutting serialization concerns requiring standardized testing + +## Consequences + +Positive: +- Serialization contract changes are caught at test time rather than runtime, preventing data corruption +- Type discriminator validation ensures versioned schemas maintain backward compatibility +- Standardized test structure improves maintainability and makes serialization behavior explicit +- Extension function tests verify boundary conversions handle edge cases like empty lists + +Negative: +- Additional test code increases maintenance burden when serialization formats change +- Exact JSON structure assertions are brittle and may require updates for cosmetic changes +- Test duplication across similar serializers may occur without shared test utilities +- Mock factory functions add indirection that may obscure actual test data + +## Alternatives + +- Use property-based testing to verify serialization round-trips without asserting exact JSON structure (rejected) + Rejected because: Does not validate exact JSON contract including field names and discriminator values required for external API compatibility + When valid: Internal serialization where only round-trip fidelity matters, not exact wire format +- Generate serialization tests automatically from schema definitions (deferred) + Rejected because: Requires additional tooling and schema-first development approach not currently in place + When valid: When adopting schema-first API design with OpenAPI or JSON Schema definitions +- Rely on integration tests to catch serialization issues (rejected) + Rejected because: Integration tests are slower, less isolated, and provide poor feedback for serialization contract violations + When valid: Never as sole verification; integration tests complement but do not replace unit-level serialization tests + +## Risks + +- Brittle tests that break on benign JSON formatting changes (e.g., property order) + Mitigation: Use JSON comparison that ignores property order; consider semantic equality checks for non-critical formatting + Owner: engineering team +- Test coverage gaps for deserialization paths and error handling + Mitigation: Extend testing standard to include deserialization tests and malformed input handling + Owner: engineering team +- Type discriminator values may conflict across different serializers + Mitigation: Establish discriminator naming conventions and maintain registry of used discriminator values + Owner: architecture team + +## Implementation Notes + +- Create test classes in src/test/kotlin mirroring the package structure of serializers under test +- Use @Test annotation and assertEquals with buildJsonObject for exact JSON structure validation +- For versioned schemas, create separate test methods for each version verifying the type discriminator field +- When testing extension functions like toSdkPolicyViews, include edge cases such as empty lists and multi-item collections +- Consider extracting mock factory functions (e.g., createMockPolicy) to shared test utilities for reuse across test classes + +## Continuation Context + + +Verify commands: +- grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l +- find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +Accept when: +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + +## Enforcement + +- Verified by: Code review checklist requiring serialization tests for new serializers +- Verified by: CI pipeline test coverage reporting for serialization packages +- Verified by: Static analysis detecting serializers without corresponding test classes +- Violation handling: Pull requests adding serializers without tests are blocked in code review +- Violation handling: Coverage reports flag untested serialization code for remediation +- Violation handling: Architecture review required for serializers lacking discriminator validation +- Exception process: Exceptions require architecture team approval with documented justification +- Exception process: Temporary exceptions must include remediation plan and timeline +- Exception process: Exception requests must demonstrate why alternative testing approach provides equivalent contract validation \ No newline at end of file diff --git a/docs/adr/0e93d40a-3759-43d3-ae74-525a465aa5a7-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-fixtures-use.md b/docs/adr/0e93d40a-3759-43d3-ae74-525a465aa5a7-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-fixtures-use.md new file mode 100644 index 00000000000..58dce7f2850 --- /dev/null +++ b/docs/adr/0e93d40a-3759-43d3-ae74-525a465aa5a7-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-fixtures-use.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Fixtures Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. SHOULD: Test fixtures SHOULD use file-based resources stored in a fixtures/ subdirectory relative to the test file + +## Policy Block + +- SHOULD Test fixtures SHOULD use file-based resources stored in a fixtures/ subdirectory relative to the test file + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/0e95ad4a-c8ed-42a9-af64-2737d2ce5b48-adopt-model-context-protocol-sdk-for-android-device-integration-fatal-errors-logged.md b/docs/adr/0e95ad4a-c8ed-42a9-af64-2737d2ce5b48-adopt-model-context-protocol-sdk-for-android-device-integration-fatal-errors-logged.md new file mode 100644 index 00000000000..ffe97e444eb --- /dev/null +++ b/docs/adr/0e95ad4a-c8ed-42a9-af64-2737d2ce5b48-adopt-model-context-protocol-sdk-for-android-device-integration-fatal-errors-logged.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Fatal Errors Logged + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. MUST: Fatal errors MUST be logged using console.error with 'Fatal error:' prefix + +## Policy Block + +- MUST Fatal errors MUST be logged using console.error with 'Fatal error:' prefix + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/0f6063db-430f-4ec7-9201-c516c50a7078-standardize-public-contract-functions-for-github-integration-automation-public-contract-functions.md b/docs/adr/0f6063db-430f-4ec7-9201-c516c50a7078-standardize-public-contract-functions-for-github-integration-automation-public-contract-functions.md new file mode 100644 index 00000000000..54a037584fd --- /dev/null +++ b/docs/adr/0f6063db-430f-4ec7-9201-c516c50a7078-standardize-public-contract-functions-for-github-integration-automation-public-contract-functions.md @@ -0,0 +1,99 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Public Contract Functions + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains automation scripts for GitHub PR labeling that require structured interaction with GitHub APIs and configuration management +- Python scripts in .github/scripts/ implement integration logic using standard library modules (argparse, json, os, subprocess, sys) without external API client libraries +- The label-pr.py script exposes public contract functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that abstract GitHub CLI interactions +- Configuration-driven pattern matching against PR titles and file paths determines label application, requiring consistent data access patterns and input validation +- The automation boundary separates internal contract functions from external GitHub API calls via subprocess invocation of gh CLI + +## Problem Statement + +GitHub automation scripts require stable, testable internal APIs for configuration loading, GitHub data retrieval, and label manipulation, but ad-hoc function definitions without explicit contracts lead to inconsistent error handling, difficult testing, and fragile integration boundaries when scripts evolve or are reused across workflows. + +## Decision + +1. MUST: Public contract functions MUST handle JSON parsing errors with explicit exception handling (json.JSONDecodeError) and provide meaningful error context + +## Policy Block + +- MUST Public contract functions MUST handle JSON parsing errors with explicit exception handling (json.JSONDecodeError) and provide meaningful error context + +## Rationale + +- The detected pattern shows consistent naming conventions (gh_* prefix) and explicit public contracts in label-pr.py, indicating intentional API design for internal reuse and testing +- Using subprocess with gh CLI rather than direct API clients reduces dependency complexity and leverages GitHub's official CLI for authentication and API versioning +- Explicit exception handling for JSON parsing and pattern matching demonstrates defensive programming at integration boundaries where external configuration drives behavior +- Set-based label manipulation (.add() operations) prevents duplicate labels and provides efficient membership testing for conditional logic + +## Consequences + +Positive: +- Clear function contracts enable unit testing of GitHub integration logic without requiring live API access or complex mocking +- Standardized naming conventions (gh_* prefix) make integration boundaries explicit and improve code discoverability +- Subprocess-based gh CLI invocation isolates authentication complexity and API versioning from script logic +- Configuration-driven pattern matching allows non-developers to modify labeling rules without code changes + +Negative: +- Subprocess invocation of gh CLI adds latency and process overhead compared to direct HTTP API calls +- Reliance on gh CLI availability creates an external dependency that must be present in CI/CD environments +- Standard library-only constraint limits access to advanced HTTP features like connection pooling, retry logic, and structured error responses +- Set-based label manipulation requires conversion overhead when interfacing with list-based GitHub API responses + +## Alternatives + +- Use PyGithub or github3.py library for direct GitHub API access with native Python objects (rejected) + Rejected because: Introduces external dependency management complexity and requires explicit authentication token handling, whereas gh CLI provides authenticated context automatically in GitHub Actions + When valid: When scripts run outside GitHub Actions environment or require advanced API features not exposed by gh CLI +- Implement inline GitHub API calls without abstraction functions (rejected) + Rejected because: Reduces testability and code reuse, making it difficult to mock external dependencies or refactor integration logic independently + When valid: For one-off scripts with no reuse requirements and no testing needs +- Create a formal Python package with typed interfaces for GitHub integration contracts (deferred) + Rejected because: Current evidence shows single-file script usage without cross-repository reuse patterns that would justify packaging overhead + When valid: When GitHub integration patterns are reused across multiple repositories or require versioned distribution + +## Risks + +- gh CLI command interface changes could break subprocess invocations without compile-time detection + Mitigation: Pin gh CLI version in CI environment and add integration tests that verify command output format + Owner: engineering team +- Configuration JSON schema drift could cause runtime failures if validation is insufficient + Mitigation: Implement explicit schema validation for required keys (title_patterns, path_patterns) with clear error messages + Owner: engineering team +- Subprocess error handling may not capture all gh CLI failure modes (network errors, rate limits, authentication failures) + Mitigation: Wrap subprocess calls with comprehensive exception handling and log stderr output for debugging + Owner: engineering team + +## Implementation Notes + +- Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions +- Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing +- Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands +- Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed + +## Continuation Context + + +Verify commands: +- grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py +- grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py +- grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +Accept when: +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Enforcement + +- Verified by: Code review checklist verifying function naming conventions and exception handling patterns +- Verified by: Automated grep-based verification in CI pipeline checking for required function prefixes and error handling +- Violation handling: PR comments requesting refactoring to match established naming conventions +- Violation handling: CI pipeline warnings when new GitHub integration functions lack proper error handling +- Exception process: Document rationale in code comments when alternative patterns are necessary +- Exception process: Obtain approval from platform team for deviations from standard contract patterns \ No newline at end of file diff --git a/docs/adr/1022ba63-742d-4d07-a9ca-ddf44b8b6f4a-standardize-public-contract-functions-for-github-integration-automation-label-manipulation-functions.md b/docs/adr/1022ba63-742d-4d07-a9ca-ddf44b8b6f4a-standardize-public-contract-functions-for-github-integration-automation-label-manipulation-functions.md new file mode 100644 index 00000000000..add025b97a5 --- /dev/null +++ b/docs/adr/1022ba63-742d-4d07-a9ca-ddf44b8b6f4a-standardize-public-contract-functions-for-github-integration-automation-label-manipulation-functions.md @@ -0,0 +1,99 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Label Manipulation Functions + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains automation scripts for GitHub PR labeling that require structured interaction with GitHub APIs and configuration management +- Python scripts in .github/scripts/ implement integration logic using standard library modules (argparse, json, os, subprocess, sys) without external API client libraries +- The label-pr.py script exposes public contract functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that abstract GitHub CLI interactions +- Configuration-driven pattern matching against PR titles and file paths determines label application, requiring consistent data access patterns and input validation +- The automation boundary separates internal contract functions from external GitHub API calls via subprocess invocation of gh CLI + +## Problem Statement + +GitHub automation scripts require stable, testable internal APIs for configuration loading, GitHub data retrieval, and label manipulation, but ad-hoc function definitions without explicit contracts lead to inconsistent error handling, difficult testing, and fragile integration boundaries when scripts evolve or are reused across workflows. + +## Decision + +1. SHOULD: Label manipulation functions SHOULD use set-based data structures for deduplication and membership testing + +## Policy Block + +- SHOULD Label manipulation functions SHOULD use set-based data structures for deduplication and membership testing + +## Rationale + +- The detected pattern shows consistent naming conventions (gh_* prefix) and explicit public contracts in label-pr.py, indicating intentional API design for internal reuse and testing +- Using subprocess with gh CLI rather than direct API clients reduces dependency complexity and leverages GitHub's official CLI for authentication and API versioning +- Explicit exception handling for JSON parsing and pattern matching demonstrates defensive programming at integration boundaries where external configuration drives behavior +- Set-based label manipulation (.add() operations) prevents duplicate labels and provides efficient membership testing for conditional logic + +## Consequences + +Positive: +- Clear function contracts enable unit testing of GitHub integration logic without requiring live API access or complex mocking +- Standardized naming conventions (gh_* prefix) make integration boundaries explicit and improve code discoverability +- Subprocess-based gh CLI invocation isolates authentication complexity and API versioning from script logic +- Configuration-driven pattern matching allows non-developers to modify labeling rules without code changes + +Negative: +- Subprocess invocation of gh CLI adds latency and process overhead compared to direct HTTP API calls +- Reliance on gh CLI availability creates an external dependency that must be present in CI/CD environments +- Standard library-only constraint limits access to advanced HTTP features like connection pooling, retry logic, and structured error responses +- Set-based label manipulation requires conversion overhead when interfacing with list-based GitHub API responses + +## Alternatives + +- Use PyGithub or github3.py library for direct GitHub API access with native Python objects (rejected) + Rejected because: Introduces external dependency management complexity and requires explicit authentication token handling, whereas gh CLI provides authenticated context automatically in GitHub Actions + When valid: When scripts run outside GitHub Actions environment or require advanced API features not exposed by gh CLI +- Implement inline GitHub API calls without abstraction functions (rejected) + Rejected because: Reduces testability and code reuse, making it difficult to mock external dependencies or refactor integration logic independently + When valid: For one-off scripts with no reuse requirements and no testing needs +- Create a formal Python package with typed interfaces for GitHub integration contracts (deferred) + Rejected because: Current evidence shows single-file script usage without cross-repository reuse patterns that would justify packaging overhead + When valid: When GitHub integration patterns are reused across multiple repositories or require versioned distribution + +## Risks + +- gh CLI command interface changes could break subprocess invocations without compile-time detection + Mitigation: Pin gh CLI version in CI environment and add integration tests that verify command output format + Owner: engineering team +- Configuration JSON schema drift could cause runtime failures if validation is insufficient + Mitigation: Implement explicit schema validation for required keys (title_patterns, path_patterns) with clear error messages + Owner: engineering team +- Subprocess error handling may not capture all gh CLI failure modes (network errors, rate limits, authentication failures) + Mitigation: Wrap subprocess calls with comprehensive exception handling and log stderr output for debugging + Owner: engineering team + +## Implementation Notes + +- Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions +- Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing +- Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands +- Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed + +## Continuation Context + + +Verify commands: +- grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py +- grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py +- grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +Accept when: +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Enforcement + +- Verified by: Code review checklist verifying function naming conventions and exception handling patterns +- Verified by: Automated grep-based verification in CI pipeline checking for required function prefixes and error handling +- Violation handling: PR comments requesting refactoring to match established naming conventions +- Violation handling: CI pipeline warnings when new GitHub integration functions lack proper error handling +- Exception process: Document rationale in code comments when alternative patterns are necessary +- Exception process: Obtain approval from platform team for deviations from standard contract patterns \ No newline at end of file diff --git a/docs/adr/10aeb070-b829-4092-aa40-68b28214a184-adopt-model-context-protocol-sdk-for-android-device-integration-stdio-transport-imported.md b/docs/adr/10aeb070-b829-4092-aa40-68b28214a184-adopt-model-context-protocol-sdk-for-android-device-integration-stdio-transport-imported.md new file mode 100644 index 00000000000..e233223a5ea --- /dev/null +++ b/docs/adr/10aeb070-b829-4092-aa40-68b28214a184-adopt-model-context-protocol-sdk-for-android-device-integration-stdio-transport-imported.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Stdio Transport Imported + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. MUST: Stdio transport MUST be imported from @modelcontextprotocol/sdk/server/stdio.js for communication channel establishment + +## Policy Block + +- MUST Stdio transport MUST be imported from @modelcontextprotocol/sdk/server/stdio.js for communication channel establishment + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/13ace594-1891-4c1a-9207-864e5b351033-enforce-schema-based-input-validation-for-public-api-endpoints-validation-failures-result.md b/docs/adr/13ace594-1891-4c1a-9207-864e5b351033-enforce-schema-based-input-validation-for-public-api-endpoints-validation-failures-result.md new file mode 100644 index 00000000000..a99c2422fbc --- /dev/null +++ b/docs/adr/13ace594-1891-4c1a-9207-864e5b351033-enforce-schema-based-input-validation-for-public-api-endpoints-validation-failures-result.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Validation Failures Result + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. MUST: Validation failures MUST result in early rejection with descriptive error messages that do not expose internal implementation details + +## Policy Block + +- MUST Validation failures MUST result in early rejection with descriptive error messages that do not expose internal implementation details + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/13e82e07-7ed6-4df2-bd40-17cf7c29ed52-standardize-public-contract-functions-for-github-integration-automation-scripts-use-standard.md b/docs/adr/13e82e07-7ed6-4df2-bd40-17cf7c29ed52-standardize-public-contract-functions-for-github-integration-automation-scripts-use-standard.md new file mode 100644 index 00000000000..01c8dc76864 --- /dev/null +++ b/docs/adr/13e82e07-7ed6-4df2-bd40-17cf7c29ed52-standardize-public-contract-functions-for-github-integration-automation-scripts-use-standard.md @@ -0,0 +1,99 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Scripts Use Standard + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains automation scripts for GitHub PR labeling that require structured interaction with GitHub APIs and configuration management +- Python scripts in .github/scripts/ implement integration logic using standard library modules (argparse, json, os, subprocess, sys) without external API client libraries +- The label-pr.py script exposes public contract functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that abstract GitHub CLI interactions +- Configuration-driven pattern matching against PR titles and file paths determines label application, requiring consistent data access patterns and input validation +- The automation boundary separates internal contract functions from external GitHub API calls via subprocess invocation of gh CLI + +## Problem Statement + +GitHub automation scripts require stable, testable internal APIs for configuration loading, GitHub data retrieval, and label manipulation, but ad-hoc function definitions without explicit contracts lead to inconsistent error handling, difficult testing, and fragile integration boundaries when scripts evolve or are reused across workflows. + +## Decision + +1. MAY: Scripts MAY use standard library modules (argparse, json, os, subprocess, sys) without introducing external dependencies for GitHub integration + +## Policy Block + +- MAY Scripts MAY use standard library modules (argparse, json, os, subprocess, sys) without introducing external dependencies for GitHub integration + +## Rationale + +- The detected pattern shows consistent naming conventions (gh_* prefix) and explicit public contracts in label-pr.py, indicating intentional API design for internal reuse and testing +- Using subprocess with gh CLI rather than direct API clients reduces dependency complexity and leverages GitHub's official CLI for authentication and API versioning +- Explicit exception handling for JSON parsing and pattern matching demonstrates defensive programming at integration boundaries where external configuration drives behavior +- Set-based label manipulation (.add() operations) prevents duplicate labels and provides efficient membership testing for conditional logic + +## Consequences + +Positive: +- Clear function contracts enable unit testing of GitHub integration logic without requiring live API access or complex mocking +- Standardized naming conventions (gh_* prefix) make integration boundaries explicit and improve code discoverability +- Subprocess-based gh CLI invocation isolates authentication complexity and API versioning from script logic +- Configuration-driven pattern matching allows non-developers to modify labeling rules without code changes + +Negative: +- Subprocess invocation of gh CLI adds latency and process overhead compared to direct HTTP API calls +- Reliance on gh CLI availability creates an external dependency that must be present in CI/CD environments +- Standard library-only constraint limits access to advanced HTTP features like connection pooling, retry logic, and structured error responses +- Set-based label manipulation requires conversion overhead when interfacing with list-based GitHub API responses + +## Alternatives + +- Use PyGithub or github3.py library for direct GitHub API access with native Python objects (rejected) + Rejected because: Introduces external dependency management complexity and requires explicit authentication token handling, whereas gh CLI provides authenticated context automatically in GitHub Actions + When valid: When scripts run outside GitHub Actions environment or require advanced API features not exposed by gh CLI +- Implement inline GitHub API calls without abstraction functions (rejected) + Rejected because: Reduces testability and code reuse, making it difficult to mock external dependencies or refactor integration logic independently + When valid: For one-off scripts with no reuse requirements and no testing needs +- Create a formal Python package with typed interfaces for GitHub integration contracts (deferred) + Rejected because: Current evidence shows single-file script usage without cross-repository reuse patterns that would justify packaging overhead + When valid: When GitHub integration patterns are reused across multiple repositories or require versioned distribution + +## Risks + +- gh CLI command interface changes could break subprocess invocations without compile-time detection + Mitigation: Pin gh CLI version in CI environment and add integration tests that verify command output format + Owner: engineering team +- Configuration JSON schema drift could cause runtime failures if validation is insufficient + Mitigation: Implement explicit schema validation for required keys (title_patterns, path_patterns) with clear error messages + Owner: engineering team +- Subprocess error handling may not capture all gh CLI failure modes (network errors, rate limits, authentication failures) + Mitigation: Wrap subprocess calls with comprehensive exception handling and log stderr output for debugging + Owner: engineering team + +## Implementation Notes + +- Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions +- Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing +- Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands +- Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed + +## Continuation Context + + +Verify commands: +- grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py +- grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py +- grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +Accept when: +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Enforcement + +- Verified by: Code review checklist verifying function naming conventions and exception handling patterns +- Verified by: Automated grep-based verification in CI pipeline checking for required function prefixes and error handling +- Violation handling: PR comments requesting refactoring to match established naming conventions +- Violation handling: CI pipeline warnings when new GitHub integration functions lack proper error handling +- Exception process: Document rationale in code comments when alternative patterns are necessary +- Exception process: Obtain approval from platform team for deviations from standard contract patterns \ No newline at end of file diff --git a/docs/adr/14cc0f9f-3d16-42a8-a5ef-ba36349bf042-adopt-hilt-dependency-injection-for-android-application-components-viewmodels-use-constructor.md b/docs/adr/14cc0f9f-3d16-42a8-a5ef-ba36349bf042-adopt-hilt-dependency-injection-for-android-application-components-viewmodels-use-constructor.md new file mode 100644 index 00000000000..1d0c6a9baa4 --- /dev/null +++ b/docs/adr/14cc0f9f-3d16-42a8-a5ef-ba36349bf042-adopt-hilt-dependency-injection-for-android-application-components-viewmodels-use-constructor.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Viewmodels Use Constructor + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. MUST: ViewModels MUST use constructor injection for all dependencies to maintain testability + +## Policy Block + +- MUST ViewModels MUST use constructor injection for all dependencies to maintain testability + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/18ee23ee-c8e0-463d-8d5a-4898ab14a630-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-descriptions-use.md b/docs/adr/18ee23ee-c8e0-463d-8d5a-4898ab14a630-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-descriptions-use.md new file mode 100644 index 00000000000..510a54f247c --- /dev/null +++ b/docs/adr/18ee23ee-c8e0-463d-8d5a-4898ab14a630-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-descriptions-use.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Test Descriptions Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. SHOULD: Test descriptions SHOULD use docstrings (Python) or string literals (TypeScript) to document test intent + +## Policy Block + +- SHOULD Test descriptions SHOULD use docstrings (Python) or string literals (TypeScript) to document test intent + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/198d8e26-bd59-4514-bbb8-36b222726207-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-custom-exception-bitwardenerror.md b/docs/adr/198d8e26-bd59-4514-bbb8-36b222726207-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-custom-exception-bitwardenerror.md new file mode 100644 index 00000000000..70c667f7e57 --- /dev/null +++ b/docs/adr/198d8e26-bd59-4514-bbb8-36b222726207-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-custom-exception-bitwardenerror.md @@ -0,0 +1,117 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Custom Exception Bitwardenerror + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Network error handling requires consistent testing patterns to validate error response parsing and exception mapping behavior +- The codebase uses custom exception types (CookieRedirectException, LocalNetworkAccessException) that must be converted to BitwardenError types with specific HTTP status codes +- OkHttp's Response.error() and ResponseBody.toResponseBody() provide a standard mechanism for creating mock HTTP error responses in unit tests +- JUnit 5 (@Test annotations) serves as the testing framework with assertion methods (assertEquals, assertTrue) for validating error transformation logic +- Error response bodies contain structured JSON with message and validationErrors fields that must be parsed and validated in test scenarios + +## Problem Statement + +Network layer error handling involves complex transformations between HTTP responses, custom exceptions, and domain error types. Without standardized testing patterns for error scenarios, teams may create inconsistent mock responses, fail to validate critical error parsing paths, or miss edge cases in exception-to-error mappings. This leads to fragile error handling code and potential runtime failures when unexpected HTTP error responses occur. + +## Decision + +1. MUST: Custom exception to BitwardenError transformations MUST be tested with JUnit 5 @Test methods that validate both error type and HTTP status code + +## Policy Block + +- MUST Custom exception to BitwardenError transformations MUST be tested with JUnit 5 @Test methods that validate both error type and HTTP status code + +In scope: +- Network layer unit tests in network/src/test/kotlin/**/*Test.kt +- Tests validating toBitwardenError() extension functions +- Tests validating parseErrorBodyOrNull() error parsing logic +- HTTP error response mocking for status codes 400-599 +- Custom exception type testing (CookieRedirectException, LocalNetworkAccessException) + +Out of scope: +- Integration tests with real HTTP clients +- End-to-end error handling flows +- UI layer error display testing +- Non-HTTP error scenarios (e.g., network timeouts, SSL errors) +- Production error logging implementation + +## Rationale + +- The evidence shows consistent use of Response.error() and toResponseBody() across 2 test files, indicating an established pattern for mocking HTTP error responses +- JUnit 5 assertions (assertEquals, assertTrue) provide type-safe validation of error transformations with clear failure messages +- Testing both exception-to-error mapping and JSON body parsing ensures comprehensive coverage of the error handling pipeline +- The pattern enables isolated unit testing of error logic without requiring actual network calls or HTTP server infrastructure + +## Consequences + +Positive: +- Consistent error response mocking reduces test code duplication and improves maintainability +- Type-safe assertions catch regressions in error transformation logic during refactoring +- Isolated unit tests execute quickly without network dependencies, enabling fast feedback loops +- Structured JSON validation ensures error messages and validation errors are correctly extracted for user display + +Negative: +- OkHttp-specific mocking creates tight coupling between tests and the HTTP client library +- Mock responses may diverge from actual server error formats if not kept synchronized +- Test coverage is limited to known error scenarios and may miss unexpected server responses +- Additional test code is required to maintain comprehensive error scenario coverage + +## Alternatives + +- Use MockWebServer to simulate full HTTP server responses for error testing (rejected) + Rejected because: MockWebServer adds complexity and slower test execution for unit-level error transformation logic that can be tested with simple mock objects + When valid: Integration tests requiring full request/response cycles with headers, redirects, and connection handling +- Create custom test fixtures or builders for BitwardenError instances (rejected) + Rejected because: Direct construction bypasses the actual transformation logic (toBitwardenError) that needs validation, reducing test coverage of production code paths + When valid: Tests focused on error handling behavior downstream of error creation, where the transformation itself is not under test +- Use property-based testing to generate random error responses (deferred) + Rejected because: Not currently implemented in the codebase; would require additional testing framework dependencies + When valid: Future enhancement to discover edge cases in error parsing logic with generated inputs + +## Risks + +- Mock error responses diverge from actual server API error formats over time + Mitigation: Maintain contract tests or API schema validation to ensure mock responses match production error formats; periodically review server API documentation + Owner: Network layer team +- OkHttp library updates may change Response.error() behavior or deprecate APIs + Mitigation: Pin OkHttp version in dependency management; review release notes during upgrades; maintain adapter layer if API changes + Owner: Engineering team +- Test coverage gaps for uncommon HTTP status codes or malformed response bodies + Mitigation: Use code coverage tools to identify untested error paths; add parameterized tests for status code ranges; include malformed JSON test cases + Owner: QA and development team + +## Implementation Notes + +- Import okhttp3.ResponseBody.Companion.toResponseBody and retrofit2.Response for creating mock error responses in test setup +- Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions +- Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability +- Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic) +- Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites + +## Continuation Context + + +Verify commands: +- grep -r "Response.error" network/src/test/kotlin/ | wc -l +- grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l +- grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l + +Accept when: +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields + +## Enforcement + +- Verified by: Code review checklist requiring error transformation tests for new exception types +- Verified by: CI pipeline test execution with minimum coverage thresholds for network error handling code +- Verified by: Static analysis to detect Response.error() usage patterns in test files +- Violation handling: Pull requests adding new error types without corresponding tests are blocked until tests are added +- Violation handling: Coverage drops in network error handling modules trigger build warnings and team notifications +- Violation handling: Quarterly audit of error test patterns identifies inconsistencies for remediation +- Exception process: Temporary exception granted for prototype or spike work with technical debt ticket created +- Exception process: Exception requires architecture team approval with documented rationale +- Exception process: All exceptions reviewed in monthly technical debt review meetings with remediation timeline \ No newline at end of file diff --git a/docs/adr/1a7cd7af-4fe9-4aee-afb0-4b1b9faa0cd4-standardize-set-based-label-management-for-external-client-boundaries-label-operations-handle.md b/docs/adr/1a7cd7af-4fe9-4aee-afb0-4b1b9faa0cd4-standardize-set-based-label-management-for-external-client-boundaries-label-operations-handle.md new file mode 100644 index 00000000000..86033c4d06c --- /dev/null +++ b/docs/adr/1a7cd7af-4fe9-4aee-afb0-4b1b9faa0cd4-standardize-set-based-label-management-for-external-client-boundaries-label-operations-handle.md @@ -0,0 +1,115 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Label Operations Handle + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes GitHub pull request metadata to classify and label changes based on title and path patterns +- External client boundaries require dynamic label assignment based on pattern matching against configuration-driven rules +- The system uses set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls +- Configuration is loaded from JSON files and parsed using standard library modules (argparse, json, os, subprocess, sys) +- The pattern emerged in automation scripts that bridge external GitHub API interactions with internal classification logic + +## Problem Statement + +When managing labels for external client boundaries such as GitHub pull requests, the system must efficiently accumulate, deduplicate, and conditionally apply labels based on pattern matching without introducing race conditions or duplicate API calls. A consistent data access pattern is needed to handle label state transitions and batch operations. + +## Decision + +1. SHOULD: Label operations SHOULD handle JSON parsing exceptions gracefully to prevent automation failures + +## Policy Block + +- SHOULD Label operations SHOULD handle JSON parsing exceptions gracefully to prevent automation failures + +In scope: +- GitHub pull request labeling automation scripts +- External client boundary interactions requiring label management +- Configuration-driven pattern matching workflows +- Set-based label accumulation and deduplication logic + +Out of scope: +- Internal database label storage or persistence +- Real-time streaming label updates +- Label management for non-GitHub external systems +- Manual label assignment workflows + +## Rationale + +- Set-based operations provide O(1) deduplication and membership testing, reducing complexity in label accumulation logic +- Batching label operations before external API calls minimizes network overhead and API rate limit consumption +- Pattern-driven configuration enables declarative label rules without code changes, improving maintainability +- The evidence shows consistent use of .add() and 'in' operators across label management, indicating an established pattern + +## Consequences + +Positive: +- Automatic deduplication prevents duplicate labels from being applied to pull requests +- Reduced API calls through batching improves performance and reduces rate limit pressure +- Declarative JSON configuration enables non-developers to modify labeling rules +- Set-based operations provide clear, idiomatic Python code that is easy to test and maintain + +Negative: +- Set-based approach loses ordering information if label application order matters +- In-memory accumulation requires all labels to be determined before any can be applied +- JSON configuration parsing adds a dependency on file I/O and introduces potential parsing errors +- Pattern matching complexity grows linearly with the number of configured patterns + +## Alternatives + +- Apply labels immediately upon pattern match without accumulation (rejected) + Rejected because: Would result in multiple API calls per PR and potential race conditions with concurrent label operations + When valid: When label order must be preserved or when real-time feedback is required +- Use list-based accumulation with manual deduplication (rejected) + Rejected because: Introduces O(n) membership checks and requires explicit deduplication logic, increasing complexity + When valid: When label ordering must be preserved or when duplicate labels have semantic meaning +- Store label state in a database with transactional updates (deferred) + Rejected because: Adds infrastructure complexity and latency for a lightweight automation script + When valid: When label history tracking, auditing, or multi-step workflows are required + +## Risks + +- JSON configuration parsing errors could cause automation failures and unlabeled pull requests + Mitigation: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting + Owner: engineering team +- Pattern matching complexity may degrade performance as configuration grows + Mitigation: Profile pattern matching performance and consider caching compiled patterns or using more efficient matching algorithms + Owner: engineering team +- Set-based deduplication may hide configuration errors where duplicate patterns exist + Mitigation: Add configuration validation to detect and warn about overlapping or duplicate patterns + Owner: engineering team + +## Implementation Notes + +- Initialize label sets early in the workflow to ensure all conditional branches can add labels safely +- Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels +- Validate JSON configuration schema on load to catch malformed patterns before runtime +- Consider logging the final label set before API calls to aid debugging and auditing +- Implement unit tests that verify set operations produce expected deduplication behavior + +## Continuation Context + + +Verify commands: +- grep -r '\.add("app:' .github/scripts/ | wc -l +- grep -r 'labels.*=.*set()' .github/scripts/ | wc -l +- python3 -m py_compile .github/scripts/label-pr.py + +Accept when: +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + +## Enforcement + +- Verified by: Code review of pull request automation scripts +- Verified by: Static analysis to detect non-set-based label accumulation patterns +- Verified by: Integration tests that verify label deduplication behavior +- Violation handling: Code review feedback requesting refactoring to set-based approach +- Violation handling: CI pipeline warnings when list-based label accumulation is detected +- Violation handling: Documentation updates to clarify the standard pattern +- Exception process: Document the specific requirement that necessitates deviation (e.g., label ordering) +- Exception process: Obtain approval from the platform engineering team +- Exception process: Add inline comments explaining why the exception is necessary \ No newline at end of file diff --git a/docs/adr/1ad0412a-5069-4826-818c-2d9c8afdc0df-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-intent-processing-logic.md b/docs/adr/1ad0412a-5069-4826-818c-2d9c8afdc0df-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-intent-processing-logic.md new file mode 100644 index 00000000000..3c11a4b457c --- /dev/null +++ b/docs/adr/1ad0412a-5069-4826-818c-2d9c8afdc0df-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-intent-processing-logic.md @@ -0,0 +1,116 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Intent Processing Logic + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Three ViewModel implementations (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel) consistently use HiltViewModel annotation for dependency injection at public API boundaries handling Android Intent-based interactions +- All three ViewModels extend BaseViewModel and coordinate external API contracts through sealed action types (CredentialProviderAction, AuthCallbackAction) and data classes for Intent processing +- The pattern appears in ViewModels managing authentication flows, credential provider operations, and autofill callbacks, indicating a standardized approach to handling Android system integration points +- Dependencies injected include AuthRepository, BitwardenCredentialManager, and CredentialProviderRequestManager, suggesting a consistent architectural layer for external API coordination + +## Problem Statement + +Android ViewModels serving as public API boundaries for system integrations (credential providers, authentication callbacks, autofill) require consistent dependency injection to ensure testability, lifecycle management, and separation of concerns. Without a standardized DI approach, these critical integration points risk inconsistent initialization, difficult testing, and tight coupling to Android framework components. + +## Decision + +1. SHOULD: Intent processing logic SHOULD be coordinated through injected repository or manager components rather than directly in ViewModel + +## Policy Block + +- SHOULD Intent processing logic SHOULD be coordinated through injected repository or manager components rather than directly in ViewModel + +In scope: +- Android ViewModels handling credential provider APIs +- ViewModels processing authentication callback Intents +- ViewModels coordinating autofill service interactions +- Any ViewModel serving as boundary between Android system services and application logic + +Out of scope: +- Internal ViewModels not exposed to Android system APIs +- Fragment or Activity ViewModels handling only UI state +- Repository or manager layer components +- Non-Android platform integrations + +Exceptions: +- EXC-001: Legacy ViewModels predating Hilt adoption that require gradual migration + +## Rationale + +- Evidence shows 100% consistency across three distinct public API boundary ViewModels (credential provider, auth callback, autofill), indicating an established architectural pattern with 91.70% confidence +- HiltViewModel annotation provides Android-aware dependency injection that respects ViewModel lifecycle and survives configuration changes, critical for Intent-based system integrations +- Sealed action types and data classes create type-safe contracts that prevent runtime errors at public API boundaries where external systems interact with application logic +- Injected repository and manager components enable testability by allowing mock implementations during unit testing of Intent processing logic + +## Consequences + +Positive: +- Consistent dependency injection pattern across all public API boundary ViewModels improves maintainability and reduces cognitive load +- HiltViewModel lifecycle management prevents memory leaks and ensures proper cleanup of resources during configuration changes +- Testability improves through constructor injection, enabling unit tests with mock repositories without Android framework dependencies +- Type-safe sealed action contracts prevent runtime errors from malformed Intent data at system integration boundaries + +Negative: +- Introduces Hilt framework dependency for all public API ViewModels, increasing build complexity and annotation processing time +- Developers must understand Hilt scoping and lifecycle rules to correctly implement ViewModels at public API boundaries +- Migration of existing ViewModels to HiltViewModel pattern requires refactoring and testing effort +- Sealed action types increase boilerplate code compared to direct Intent parameter passing + +## Alternatives + +- Use manual ViewModel factory pattern with direct constructor injection (rejected) + Rejected because: Manual factory pattern requires boilerplate for each ViewModel and does not integrate with Android lifecycle-aware components as seamlessly as Hilt + When valid: In projects without Hilt or when minimizing annotation processing overhead is critical +- Use Dagger without Hilt for ViewModel injection (rejected) + Rejected because: Dagger alone requires more boilerplate and manual component management compared to Hilt's Android-specific optimizations + When valid: In projects with existing Dagger infrastructure where Hilt migration cost is prohibitive +- Use service locator pattern for dependency resolution in ViewModels (rejected) + Rejected because: Service locator pattern hides dependencies, reduces testability, and creates runtime dependency resolution failures instead of compile-time errors + When valid: Never recommended for new code; only acceptable in legacy codebases during gradual migration + +## Risks + +- Hilt annotation processing failures could break builds for all public API ViewModels simultaneously + Mitigation: Maintain Hilt version compatibility matrix, use Gradle dependency locking, and implement CI build verification for annotation processing + Owner: Engineering team +- Developers unfamiliar with Hilt may incorrectly scope dependencies, causing memory leaks or premature disposal + Mitigation: Provide ViewModel dependency injection guidelines, code review checklist, and automated lint rules to detect incorrect scoping + Owner: Architecture team +- Sealed action types may grow complex as public API contracts evolve, reducing maintainability + Mitigation: Establish action type design guidelines limiting nesting depth, use composition over inheritance, and refactor when action hierarchies exceed three levels + Owner: Engineering team + +## Implementation Notes + +- Annotate all public API boundary ViewModels with @HiltViewModel and ensure constructor parameters are annotated with @Inject +- Define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic +- Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel +- Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l +- grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l +- find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l + +Accept when: +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters + +## Enforcement + +- Verified by: Code review checklist requiring HiltViewModel annotation for all public API boundary ViewModels +- Verified by: Custom lint rule detecting ViewModels with Intent parameters lacking @HiltViewModel annotation +- Verified by: CI pipeline verification step running grep commands to validate pattern compliance +- Violation handling: CI build fails if public API ViewModels lack @HiltViewModel annotation +- Violation handling: Code review blocks merge if sealed action types are not used for Intent-based contracts +- Violation handling: Architecture team notified of violations for pattern compliance tracking +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in ADR exceptions registry with approval date and review schedule +- Exception process: Re-evaluate exception quarterly to assess migration feasibility \ No newline at end of file diff --git a/docs/adr/1ba7e0e8-f59d-4593-87e9-5ff0142cd818-standardize-collection-find-pattern-for-in-memory-data-queries-avoid-manual-iteration.md b/docs/adr/1ba7e0e8-f59d-4593-87e9-5ff0142cd818-standardize-collection-find-pattern-for-in-memory-data-queries-avoid-manual-iteration.md new file mode 100644 index 00000000000..b8e85aad734 --- /dev/null +++ b/docs/adr/1ba7e0e8-f59d-4593-87e9-5ff0142cd818-standardize-collection-find-pattern-for-in-memory-data-queries-avoid-manual-iteration.md @@ -0,0 +1,100 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Avoid Manual Iteration + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase demonstrates consistent use of JavaScript/TypeScript Array.find() method for querying in-memory collections across test specifications and automation scripts +- Test files in android-device-server use .find() with predicate functions to locate specific window objects by name property from parsed dumpsys output +- Python automation scripts use Set.add() operations for label and package name collection, indicating a pattern of in-memory data accumulation and membership testing +- The pattern appears in both testing contexts (vitest test suites) and operational contexts (GitHub automation scripts, JSON validation utilities) + +## Problem Statement + +Teams need a consistent, predictable approach for querying in-memory data structures to locate specific elements by property matching, particularly when working with parsed system output, configuration data, and test fixtures. Without standardization, different query patterns emerge that reduce code readability and increase cognitive load when navigating between modules. + +## Decision + +1. SHOULD_NOT: Avoid manual iteration with for-loops when Array.find() or Set operations provide equivalent functionality with clearer intent + +## Policy Block + +- SHOULD_NOT Avoid manual iteration with for-loops when Array.find() or Set operations provide equivalent functionality with clearer intent + +## Rationale + +- The pattern is observed across 3 files with 90.83% confidence, demonstrating consistent adoption in both test infrastructure and operational automation +- Array.find() provides clear semantic intent for single-element lookup operations, improving code readability compared to manual iteration +- Set.add() operations in Python scripts demonstrate parallel pattern of using language-native collection operations for membership and uniqueness constraints +- The pattern aligns with functional programming principles and modern JavaScript/TypeScript idioms, reducing imperative boilerplate + +## Consequences + +Positive: +- Improved code readability through consistent use of declarative collection query methods +- Reduced cognitive load when navigating between test specifications and automation scripts +- Better alignment with modern JavaScript/TypeScript idioms and functional programming patterns +- Clearer semantic intent in data access operations, making code review and maintenance easier + +Negative: +- Developers unfamiliar with functional array methods may require additional training or documentation +- Predicate function overhead may introduce minor performance cost compared to manual iteration in performance-critical paths +- Pattern may not extend cleanly to languages without first-class function support or equivalent collection APIs + +## Alternatives + +- Use manual for-loop iteration with conditional breaks for element lookup (rejected) + Rejected because: Manual iteration increases boilerplate code and reduces semantic clarity compared to declarative Array.find() method + When valid: Performance-critical paths where predicate function overhead is measured and significant +- Use Array.filter() followed by index access [0] for single-element lookup (rejected) + Rejected because: Array.filter() processes entire collection even after match is found, introducing unnecessary performance overhead + When valid: When subsequent operations require the filtered array or multiple matches are possible +- Use Map or Object lookup with key-based access instead of predicate-based search (deferred) + Rejected because: null + When valid: When data structure can be pre-indexed by lookup key and multiple queries justify indexing overhead + +## Risks + +- Performance degradation in large collections if .find() is used in tight loops or performance-critical paths + Mitigation: Profile data access patterns and consider pre-indexing with Map/Object for frequently queried large collections + Owner: engineering team +- Inconsistent adoption across polyglot codebase where Python, JavaScript, and TypeScript have different collection APIs + Mitigation: Document language-specific equivalents (Python: next(filter()), JavaScript/TypeScript: Array.find()) in coding standards + Owner: engineering team +- Undefined return values from .find() may cause runtime errors if not properly handled with null checks + Mitigation: Enforce TypeScript strict null checks and require explicit undefined handling in code review + Owner: engineering team + +## Implementation Notes + +- Use TypeScript strict mode to enforce null/undefined handling for .find() return values +- Consider creating utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication +- Document the pattern in coding standards with examples from dumpsys.spec.ts showing window lookup by name property +- For Python code, use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find() + +## Continuation Context + + +Verify commands: +- grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . +- grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' +- npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' + +Accept when: +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + +## Enforcement + +- Verified by: Code review checklist includes verification of collection query patterns +- Verified by: ESLint rules configured to discourage manual iteration where Array methods are applicable +- Verified by: Test coverage requirements ensure query operations are tested with expected and missing elements +- Violation handling: Code review feedback requests refactoring of manual iteration to declarative collection methods +- Violation handling: ESLint warnings flagged in CI pipeline for review before merge +- Violation handling: Documentation links provided to developers during code review for pattern examples +- Exception process: Performance-critical paths may use manual iteration if profiling demonstrates measurable impact +- Exception process: Exception requests must include benchmark data comparing Array.find() vs manual iteration +- Exception process: Approved exceptions documented inline with comments explaining performance justification \ No newline at end of file diff --git a/docs/adr/1ecc1baf-393e-4a64-b544-82bf87d0fda2-standardize-public-contract-functions-for-github-integration-automation-configuration-loading-functions.md b/docs/adr/1ecc1baf-393e-4a64-b544-82bf87d0fda2-standardize-public-contract-functions-for-github-integration-automation-configuration-loading-functions.md new file mode 100644 index 00000000000..1827f2bccb5 --- /dev/null +++ b/docs/adr/1ecc1baf-393e-4a64-b544-82bf87d0fda2-standardize-public-contract-functions-for-github-integration-automation-configuration-loading-functions.md @@ -0,0 +1,99 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Configuration Loading Functions + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains automation scripts for GitHub PR labeling that require structured interaction with GitHub APIs and configuration management +- Python scripts in .github/scripts/ implement integration logic using standard library modules (argparse, json, os, subprocess, sys) without external API client libraries +- The label-pr.py script exposes public contract functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that abstract GitHub CLI interactions +- Configuration-driven pattern matching against PR titles and file paths determines label application, requiring consistent data access patterns and input validation +- The automation boundary separates internal contract functions from external GitHub API calls via subprocess invocation of gh CLI + +## Problem Statement + +GitHub automation scripts require stable, testable internal APIs for configuration loading, GitHub data retrieval, and label manipulation, but ad-hoc function definitions without explicit contracts lead to inconsistent error handling, difficult testing, and fragile integration boundaries when scripts evolve or are reused across workflows. + +## Decision + +1. SHOULD: Configuration loading functions SHOULD validate input data structure including required keys (title_patterns, path_patterns) before returning to callers + +## Policy Block + +- SHOULD Configuration loading functions SHOULD validate input data structure including required keys (title_patterns, path_patterns) before returning to callers + +## Rationale + +- The detected pattern shows consistent naming conventions (gh_* prefix) and explicit public contracts in label-pr.py, indicating intentional API design for internal reuse and testing +- Using subprocess with gh CLI rather than direct API clients reduces dependency complexity and leverages GitHub's official CLI for authentication and API versioning +- Explicit exception handling for JSON parsing and pattern matching demonstrates defensive programming at integration boundaries where external configuration drives behavior +- Set-based label manipulation (.add() operations) prevents duplicate labels and provides efficient membership testing for conditional logic + +## Consequences + +Positive: +- Clear function contracts enable unit testing of GitHub integration logic without requiring live API access or complex mocking +- Standardized naming conventions (gh_* prefix) make integration boundaries explicit and improve code discoverability +- Subprocess-based gh CLI invocation isolates authentication complexity and API versioning from script logic +- Configuration-driven pattern matching allows non-developers to modify labeling rules without code changes + +Negative: +- Subprocess invocation of gh CLI adds latency and process overhead compared to direct HTTP API calls +- Reliance on gh CLI availability creates an external dependency that must be present in CI/CD environments +- Standard library-only constraint limits access to advanced HTTP features like connection pooling, retry logic, and structured error responses +- Set-based label manipulation requires conversion overhead when interfacing with list-based GitHub API responses + +## Alternatives + +- Use PyGithub or github3.py library for direct GitHub API access with native Python objects (rejected) + Rejected because: Introduces external dependency management complexity and requires explicit authentication token handling, whereas gh CLI provides authenticated context automatically in GitHub Actions + When valid: When scripts run outside GitHub Actions environment or require advanced API features not exposed by gh CLI +- Implement inline GitHub API calls without abstraction functions (rejected) + Rejected because: Reduces testability and code reuse, making it difficult to mock external dependencies or refactor integration logic independently + When valid: For one-off scripts with no reuse requirements and no testing needs +- Create a formal Python package with typed interfaces for GitHub integration contracts (deferred) + Rejected because: Current evidence shows single-file script usage without cross-repository reuse patterns that would justify packaging overhead + When valid: When GitHub integration patterns are reused across multiple repositories or require versioned distribution + +## Risks + +- gh CLI command interface changes could break subprocess invocations without compile-time detection + Mitigation: Pin gh CLI version in CI environment and add integration tests that verify command output format + Owner: engineering team +- Configuration JSON schema drift could cause runtime failures if validation is insufficient + Mitigation: Implement explicit schema validation for required keys (title_patterns, path_patterns) with clear error messages + Owner: engineering team +- Subprocess error handling may not capture all gh CLI failure modes (network errors, rate limits, authentication failures) + Mitigation: Wrap subprocess calls with comprehensive exception handling and log stderr output for debugging + Owner: engineering team + +## Implementation Notes + +- Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions +- Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing +- Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands +- Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed + +## Continuation Context + + +Verify commands: +- grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py +- grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py +- grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +Accept when: +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Enforcement + +- Verified by: Code review checklist verifying function naming conventions and exception handling patterns +- Verified by: Automated grep-based verification in CI pipeline checking for required function prefixes and error handling +- Violation handling: PR comments requesting refactoring to match established naming conventions +- Violation handling: CI pipeline warnings when new GitHub integration functions lack proper error handling +- Exception process: Document rationale in code comments when alternative patterns are necessary +- Exception process: Obtain approval from platform team for deviations from standard contract patterns \ No newline at end of file diff --git a/docs/adr/243cb603-fb8b-4db7-9f37-18ff5b0c99fe-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-components-use-inject.md b/docs/adr/243cb603-fb8b-4db7-9f37-18ff5b0c99fe-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-components-use-inject.md new file mode 100644 index 00000000000..68bf426b975 --- /dev/null +++ b/docs/adr/243cb603-fb8b-4db7-9f37-18ff5b0c99fe-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-components-use-inject.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Components Use Inject + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. MAY: Components MAY use @Inject for field injection when constructor injection is not feasible + +## Policy Block + +- MAY Components MAY use @Inject for field injection when constructor injection is not feasible + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/2449364d-4257-4659-b3a9-4e88ad892e92-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-updates-use.md b/docs/adr/2449364d-4257-4659-b3a9-4e88ad892e92-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-updates-use.md new file mode 100644 index 00000000000..38ad776710f --- /dev/null +++ b/docs/adr/2449364d-4257-4659-b3a9-4e88ad892e92-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-updates-use.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: State Updates Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. MUST: State updates MUST use mutableStateFlow.update with copy operations to ensure atomic, thread-safe state transitions + +## Policy Block + +- MUST State updates MUST use mutableStateFlow.update with copy operations to ensure atomic, thread-safe state transitions + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/25181f2a-4b4a-421b-aef2-cbc5c9b1949e-standardize-set-based-label-management-for-external-client-boundaries-configuration-pattern-matching.md b/docs/adr/25181f2a-4b4a-421b-aef2-cbc5c9b1949e-standardize-set-based-label-management-for-external-client-boundaries-configuration-pattern-matching.md new file mode 100644 index 00000000000..c44579fc592 --- /dev/null +++ b/docs/adr/25181f2a-4b4a-421b-aef2-cbc5c9b1949e-standardize-set-based-label-management-for-external-client-boundaries-configuration-pattern-matching.md @@ -0,0 +1,115 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Configuration Pattern Matching + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes GitHub pull request metadata to classify and label changes based on title and path patterns +- External client boundaries require dynamic label assignment based on pattern matching against configuration-driven rules +- The system uses set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls +- Configuration is loaded from JSON files and parsed using standard library modules (argparse, json, os, subprocess, sys) +- The pattern emerged in automation scripts that bridge external GitHub API interactions with internal classification logic + +## Problem Statement + +When managing labels for external client boundaries such as GitHub pull requests, the system must efficiently accumulate, deduplicate, and conditionally apply labels based on pattern matching without introducing race conditions or duplicate API calls. A consistent data access pattern is needed to handle label state transitions and batch operations. + +## Decision + +1. SHOULD: Configuration for pattern matching SHOULD be loaded from JSON files using security-validated input parsing + +## Policy Block + +- SHOULD Configuration for pattern matching SHOULD be loaded from JSON files using security-validated input parsing + +In scope: +- GitHub pull request labeling automation scripts +- External client boundary interactions requiring label management +- Configuration-driven pattern matching workflows +- Set-based label accumulation and deduplication logic + +Out of scope: +- Internal database label storage or persistence +- Real-time streaming label updates +- Label management for non-GitHub external systems +- Manual label assignment workflows + +## Rationale + +- Set-based operations provide O(1) deduplication and membership testing, reducing complexity in label accumulation logic +- Batching label operations before external API calls minimizes network overhead and API rate limit consumption +- Pattern-driven configuration enables declarative label rules without code changes, improving maintainability +- The evidence shows consistent use of .add() and 'in' operators across label management, indicating an established pattern + +## Consequences + +Positive: +- Automatic deduplication prevents duplicate labels from being applied to pull requests +- Reduced API calls through batching improves performance and reduces rate limit pressure +- Declarative JSON configuration enables non-developers to modify labeling rules +- Set-based operations provide clear, idiomatic Python code that is easy to test and maintain + +Negative: +- Set-based approach loses ordering information if label application order matters +- In-memory accumulation requires all labels to be determined before any can be applied +- JSON configuration parsing adds a dependency on file I/O and introduces potential parsing errors +- Pattern matching complexity grows linearly with the number of configured patterns + +## Alternatives + +- Apply labels immediately upon pattern match without accumulation (rejected) + Rejected because: Would result in multiple API calls per PR and potential race conditions with concurrent label operations + When valid: When label order must be preserved or when real-time feedback is required +- Use list-based accumulation with manual deduplication (rejected) + Rejected because: Introduces O(n) membership checks and requires explicit deduplication logic, increasing complexity + When valid: When label ordering must be preserved or when duplicate labels have semantic meaning +- Store label state in a database with transactional updates (deferred) + Rejected because: Adds infrastructure complexity and latency for a lightweight automation script + When valid: When label history tracking, auditing, or multi-step workflows are required + +## Risks + +- JSON configuration parsing errors could cause automation failures and unlabeled pull requests + Mitigation: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting + Owner: engineering team +- Pattern matching complexity may degrade performance as configuration grows + Mitigation: Profile pattern matching performance and consider caching compiled patterns or using more efficient matching algorithms + Owner: engineering team +- Set-based deduplication may hide configuration errors where duplicate patterns exist + Mitigation: Add configuration validation to detect and warn about overlapping or duplicate patterns + Owner: engineering team + +## Implementation Notes + +- Initialize label sets early in the workflow to ensure all conditional branches can add labels safely +- Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels +- Validate JSON configuration schema on load to catch malformed patterns before runtime +- Consider logging the final label set before API calls to aid debugging and auditing +- Implement unit tests that verify set operations produce expected deduplication behavior + +## Continuation Context + + +Verify commands: +- grep -r '\.add("app:' .github/scripts/ | wc -l +- grep -r 'labels.*=.*set()' .github/scripts/ | wc -l +- python3 -m py_compile .github/scripts/label-pr.py + +Accept when: +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + +## Enforcement + +- Verified by: Code review of pull request automation scripts +- Verified by: Static analysis to detect non-set-based label accumulation patterns +- Verified by: Integration tests that verify label deduplication behavior +- Violation handling: Code review feedback requesting refactoring to set-based approach +- Violation handling: CI pipeline warnings when list-based label accumulation is detected +- Violation handling: Documentation updates to clarify the standard pattern +- Exception process: Document the specific requirement that necessitates deviation (e.g., label ordering) +- Exception process: Obtain approval from the platform engineering team +- Exception process: Add inline comments explaining why the exception is necessary \ No newline at end of file diff --git a/docs/adr/270e7300-2101-4791-bc58-0b9520e1145f-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-tests-suppress-stdout.md b/docs/adr/270e7300-2101-4791-bc58-0b9520e1145f-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-tests-suppress-stdout.md new file mode 100644 index 00000000000..e6a21e40605 --- /dev/null +++ b/docs/adr/270e7300-2101-4791-bc58-0b9520e1145f-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-tests-suppress-stdout.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Tests Suppress Stdout + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. MAY: Tests MAY suppress stdout/stderr using patches or context managers when testing CLI utilities to reduce noise + +## Policy Block + +- MAY Tests MAY suppress stdout/stderr using patches or context managers when testing CLI utilities to reduce noise + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/270f5ea8-6f63-45b7-b26b-02e89a5929ca-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-public-action-contracts.md b/docs/adr/270f5ea8-6f63-45b7-b26b-02e89a5929ca-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-public-action-contracts.md new file mode 100644 index 00000000000..ef376ff9cfc --- /dev/null +++ b/docs/adr/270f5ea8-6f63-45b7-b26b-02e89a5929ca-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-public-action-contracts.md @@ -0,0 +1,116 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Public Action Contracts + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Three ViewModel implementations (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel) consistently use HiltViewModel annotation for dependency injection at public API boundaries handling Android Intent-based interactions +- All three ViewModels extend BaseViewModel and coordinate external API contracts through sealed action types (CredentialProviderAction, AuthCallbackAction) and data classes for Intent processing +- The pattern appears in ViewModels managing authentication flows, credential provider operations, and autofill callbacks, indicating a standardized approach to handling Android system integration points +- Dependencies injected include AuthRepository, BitwardenCredentialManager, and CredentialProviderRequestManager, suggesting a consistent architectural layer for external API coordination + +## Problem Statement + +Android ViewModels serving as public API boundaries for system integrations (credential providers, authentication callbacks, autofill) require consistent dependency injection to ensure testability, lifecycle management, and separation of concerns. Without a standardized DI approach, these critical integration points risk inconsistent initialization, difficult testing, and tight coupling to Android framework components. + +## Decision + +1. MUST: Public API action contracts MUST be expressed as sealed classes or interfaces to enforce type-safe event handling + +## Policy Block + +- MUST Public API action contracts MUST be expressed as sealed classes or interfaces to enforce type-safe event handling + +In scope: +- Android ViewModels handling credential provider APIs +- ViewModels processing authentication callback Intents +- ViewModels coordinating autofill service interactions +- Any ViewModel serving as boundary between Android system services and application logic + +Out of scope: +- Internal ViewModels not exposed to Android system APIs +- Fragment or Activity ViewModels handling only UI state +- Repository or manager layer components +- Non-Android platform integrations + +Exceptions: +- EXC-001: Legacy ViewModels predating Hilt adoption that require gradual migration + +## Rationale + +- Evidence shows 100% consistency across three distinct public API boundary ViewModels (credential provider, auth callback, autofill), indicating an established architectural pattern with 91.70% confidence +- HiltViewModel annotation provides Android-aware dependency injection that respects ViewModel lifecycle and survives configuration changes, critical for Intent-based system integrations +- Sealed action types and data classes create type-safe contracts that prevent runtime errors at public API boundaries where external systems interact with application logic +- Injected repository and manager components enable testability by allowing mock implementations during unit testing of Intent processing logic + +## Consequences + +Positive: +- Consistent dependency injection pattern across all public API boundary ViewModels improves maintainability and reduces cognitive load +- HiltViewModel lifecycle management prevents memory leaks and ensures proper cleanup of resources during configuration changes +- Testability improves through constructor injection, enabling unit tests with mock repositories without Android framework dependencies +- Type-safe sealed action contracts prevent runtime errors from malformed Intent data at system integration boundaries + +Negative: +- Introduces Hilt framework dependency for all public API ViewModels, increasing build complexity and annotation processing time +- Developers must understand Hilt scoping and lifecycle rules to correctly implement ViewModels at public API boundaries +- Migration of existing ViewModels to HiltViewModel pattern requires refactoring and testing effort +- Sealed action types increase boilerplate code compared to direct Intent parameter passing + +## Alternatives + +- Use manual ViewModel factory pattern with direct constructor injection (rejected) + Rejected because: Manual factory pattern requires boilerplate for each ViewModel and does not integrate with Android lifecycle-aware components as seamlessly as Hilt + When valid: In projects without Hilt or when minimizing annotation processing overhead is critical +- Use Dagger without Hilt for ViewModel injection (rejected) + Rejected because: Dagger alone requires more boilerplate and manual component management compared to Hilt's Android-specific optimizations + When valid: In projects with existing Dagger infrastructure where Hilt migration cost is prohibitive +- Use service locator pattern for dependency resolution in ViewModels (rejected) + Rejected because: Service locator pattern hides dependencies, reduces testability, and creates runtime dependency resolution failures instead of compile-time errors + When valid: Never recommended for new code; only acceptable in legacy codebases during gradual migration + +## Risks + +- Hilt annotation processing failures could break builds for all public API ViewModels simultaneously + Mitigation: Maintain Hilt version compatibility matrix, use Gradle dependency locking, and implement CI build verification for annotation processing + Owner: Engineering team +- Developers unfamiliar with Hilt may incorrectly scope dependencies, causing memory leaks or premature disposal + Mitigation: Provide ViewModel dependency injection guidelines, code review checklist, and automated lint rules to detect incorrect scoping + Owner: Architecture team +- Sealed action types may grow complex as public API contracts evolve, reducing maintainability + Mitigation: Establish action type design guidelines limiting nesting depth, use composition over inheritance, and refactor when action hierarchies exceed three levels + Owner: Engineering team + +## Implementation Notes + +- Annotate all public API boundary ViewModels with @HiltViewModel and ensure constructor parameters are annotated with @Inject +- Define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic +- Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel +- Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l +- grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l +- find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l + +Accept when: +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters + +## Enforcement + +- Verified by: Code review checklist requiring HiltViewModel annotation for all public API boundary ViewModels +- Verified by: Custom lint rule detecting ViewModels with Intent parameters lacking @HiltViewModel annotation +- Verified by: CI pipeline verification step running grep commands to validate pattern compliance +- Violation handling: CI build fails if public API ViewModels lack @HiltViewModel annotation +- Violation handling: Code review blocks merge if sealed action types are not used for Intent-based contracts +- Violation handling: Architecture team notified of violations for pattern compliance tracking +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in ADR exceptions registry with approval date and review schedule +- Exception process: Re-evaluate exception quarterly to assess migration feasibility \ No newline at end of file diff --git a/docs/adr/27a4b14f-c454-4d0a-9fc6-5fee8f57ce91-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-methods-use.md b/docs/adr/27a4b14f-c454-4d0a-9fc6-5fee8f57ce91-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-methods-use.md new file mode 100644 index 00000000000..3132b51b984 --- /dev/null +++ b/docs/adr/27a4b14f-c454-4d0a-9fc6-5fee8f57ce91-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-methods-use.md @@ -0,0 +1,117 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Test Methods Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Network error handling requires consistent testing patterns to validate error response parsing and exception mapping behavior +- The codebase uses custom exception types (CookieRedirectException, LocalNetworkAccessException) that must be converted to BitwardenError types with specific HTTP status codes +- OkHttp's Response.error() and ResponseBody.toResponseBody() provide a standard mechanism for creating mock HTTP error responses in unit tests +- JUnit 5 (@Test annotations) serves as the testing framework with assertion methods (assertEquals, assertTrue) for validating error transformation logic +- Error response bodies contain structured JSON with message and validationErrors fields that must be parsed and validated in test scenarios + +## Problem Statement + +Network layer error handling involves complex transformations between HTTP responses, custom exceptions, and domain error types. Without standardized testing patterns for error scenarios, teams may create inconsistent mock responses, fail to validate critical error parsing paths, or miss edge cases in exception-to-error mappings. This leads to fragile error handling code and potential runtime failures when unexpected HTTP error responses occur. + +## Decision + +1. SHOULD: Test methods SHOULD use assertTrue for type checking error instances before casting to specific error types + +## Policy Block + +- SHOULD Test methods SHOULD use assertTrue for type checking error instances before casting to specific error types + +In scope: +- Network layer unit tests in network/src/test/kotlin/**/*Test.kt +- Tests validating toBitwardenError() extension functions +- Tests validating parseErrorBodyOrNull() error parsing logic +- HTTP error response mocking for status codes 400-599 +- Custom exception type testing (CookieRedirectException, LocalNetworkAccessException) + +Out of scope: +- Integration tests with real HTTP clients +- End-to-end error handling flows +- UI layer error display testing +- Non-HTTP error scenarios (e.g., network timeouts, SSL errors) +- Production error logging implementation + +## Rationale + +- The evidence shows consistent use of Response.error() and toResponseBody() across 2 test files, indicating an established pattern for mocking HTTP error responses +- JUnit 5 assertions (assertEquals, assertTrue) provide type-safe validation of error transformations with clear failure messages +- Testing both exception-to-error mapping and JSON body parsing ensures comprehensive coverage of the error handling pipeline +- The pattern enables isolated unit testing of error logic without requiring actual network calls or HTTP server infrastructure + +## Consequences + +Positive: +- Consistent error response mocking reduces test code duplication and improves maintainability +- Type-safe assertions catch regressions in error transformation logic during refactoring +- Isolated unit tests execute quickly without network dependencies, enabling fast feedback loops +- Structured JSON validation ensures error messages and validation errors are correctly extracted for user display + +Negative: +- OkHttp-specific mocking creates tight coupling between tests and the HTTP client library +- Mock responses may diverge from actual server error formats if not kept synchronized +- Test coverage is limited to known error scenarios and may miss unexpected server responses +- Additional test code is required to maintain comprehensive error scenario coverage + +## Alternatives + +- Use MockWebServer to simulate full HTTP server responses for error testing (rejected) + Rejected because: MockWebServer adds complexity and slower test execution for unit-level error transformation logic that can be tested with simple mock objects + When valid: Integration tests requiring full request/response cycles with headers, redirects, and connection handling +- Create custom test fixtures or builders for BitwardenError instances (rejected) + Rejected because: Direct construction bypasses the actual transformation logic (toBitwardenError) that needs validation, reducing test coverage of production code paths + When valid: Tests focused on error handling behavior downstream of error creation, where the transformation itself is not under test +- Use property-based testing to generate random error responses (deferred) + Rejected because: Not currently implemented in the codebase; would require additional testing framework dependencies + When valid: Future enhancement to discover edge cases in error parsing logic with generated inputs + +## Risks + +- Mock error responses diverge from actual server API error formats over time + Mitigation: Maintain contract tests or API schema validation to ensure mock responses match production error formats; periodically review server API documentation + Owner: Network layer team +- OkHttp library updates may change Response.error() behavior or deprecate APIs + Mitigation: Pin OkHttp version in dependency management; review release notes during upgrades; maintain adapter layer if API changes + Owner: Engineering team +- Test coverage gaps for uncommon HTTP status codes or malformed response bodies + Mitigation: Use code coverage tools to identify untested error paths; add parameterized tests for status code ranges; include malformed JSON test cases + Owner: QA and development team + +## Implementation Notes + +- Import okhttp3.ResponseBody.Companion.toResponseBody and retrofit2.Response for creating mock error responses in test setup +- Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions +- Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability +- Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic) +- Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites + +## Continuation Context + + +Verify commands: +- grep -r "Response.error" network/src/test/kotlin/ | wc -l +- grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l +- grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l + +Accept when: +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields + +## Enforcement + +- Verified by: Code review checklist requiring error transformation tests for new exception types +- Verified by: CI pipeline test execution with minimum coverage thresholds for network error handling code +- Verified by: Static analysis to detect Response.error() usage patterns in test files +- Violation handling: Pull requests adding new error types without corresponding tests are blocked until tests are added +- Violation handling: Coverage drops in network error handling modules trigger build warnings and team notifications +- Violation handling: Quarterly audit of error test patterns identifies inconsistencies for remediation +- Exception process: Temporary exception granted for prototype or spike work with technical debt ticket created +- Exception process: Exception requires architecture team approval with documented rationale +- Exception process: All exceptions reviewed in monthly technical debt review meetings with remediation timeline \ No newline at end of file diff --git a/docs/adr/27e5a784-711c-42af-b6dd-7ab5561d68f1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-handler-screen-components.md b/docs/adr/27e5a784-711c-42af-b6dd-7ab5561d68f1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-handler-screen-components.md new file mode 100644 index 00000000000..bc3ca91080f --- /dev/null +++ b/docs/adr/27e5a784-711c-42af-b6dd-7ab5561d68f1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-handler-screen-components.md @@ -0,0 +1,123 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Handler Screen Components + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all UI component development in the Android application codebase. + +## Context + +- The Android application uses Jetpack Compose as the declarative UI framework, requiring the @Composable annotation to mark functions that emit UI elements +- Three screen implementation files in the auth feature module (SetupUnlockScreen.kt, ExpiredRegistrationLinkScreen.kt, CompleteRegistrationHandler.kt) consistently use @Composable functions with androidx.compose.* foundation and runtime libraries +- The codebase demonstrates a pattern of composing UI hierarchies using androidx.compose.foundation.layout components (Column, Row, Spacer) and androidx.compose.runtime utilities (remember, Composable) +- The detection spans authentication-related UI screens, indicating organization-wide adoption of Compose for user-facing interface construction + +## Problem Statement + +Android UI development requires a consistent framework for declaring composable UI components that integrate with the Jetpack Compose runtime, ensuring proper recomposition behavior, state management, and layout composition across all screen implementations. + +## Decision + +1. SHOULD: Handler and screen components SHOULD separate UI composition logic from business logic using ViewModel integration patterns + +## Policy Block + +- SHOULD Handler and screen components SHOULD separate UI composition logic from business logic using ViewModel integration patterns + +In scope: +- All Android UI screen implementations in app/src/main/kotlin UI packages +- Authentication feature module UI components +- Any function that directly or indirectly emits Compose UI elements +- Handler components that coordinate UI composition with ViewModels + +Out of scope: +- ViewModel classes and business logic layers +- Data repository and network layer implementations +- Utility functions that do not emit UI +- Android View system components (legacy XML-based UI) +- Unit test files and test utilities + +Exceptions: +- EXC-001: Interoperating with legacy Android View system components during migration +- EXC-002: Preview functions for Android Studio Compose preview tooling + +## Rationale + +- Evidence from 3 files shows consistent use of @Composable annotation with 92.50% confidence, indicating established organizational practice +- Jetpack Compose provides declarative UI construction with automatic recomposition, reducing boilerplate and state synchronization complexity compared to imperative View system +- The androidx.compose.foundation and androidx.compose.runtime libraries form the core dependency set observed across all detected files, establishing a stable API surface +- Standardizing on @Composable annotation ensures compile-time verification of composable function constraints and enables Compose compiler optimizations + +## Consequences + +Positive: +- Declarative UI composition reduces state management complexity and eliminates manual view updates +- Compose compiler enforces composable function constraints at compile-time, catching errors early +- Consistent use of androidx.compose.* libraries provides a unified API surface for UI development +- Improved developer productivity through reduced boilerplate and better tooling support (preview, inspection) + +Negative: +- Requires learning curve for developers familiar with traditional Android View system +- Increases APK size due to Compose runtime library dependencies +- Limited interoperability with legacy View-based components requires AndroidView wrappers +- Compose compiler plugin adds build time overhead for annotation processing + +## Alternatives + +- Continue using traditional Android View system with XML layouts and findViewById (rejected) + Rejected because: Imperative View system requires manual state synchronization, increases boilerplate, and lacks compile-time UI verification. Evidence shows organization has already committed to Compose. + When valid: Only for legacy modules not yet migrated or when specific View components have no Compose equivalent +- Adopt alternative declarative UI frameworks (Flutter, React Native) (rejected) + Rejected because: Would require complete platform rewrite and abandonment of native Android tooling. Evidence shows deep integration with androidx.compose.* libraries. + When valid: For new greenfield projects with cross-platform requirements from inception +- Hybrid approach mixing Compose and View system components (deferred) + Rejected because: Not rejected but deferred as a migration strategy. Evidence shows pure Compose adoption in detected files. + When valid: During migration period for legacy screens not yet converted to Compose + +## Risks + +- Compose API instability or breaking changes in androidx.compose.* libraries during version upgrades + Mitigation: Pin Compose library versions in dependency management, test thoroughly before upgrading, monitor Compose release notes + Owner: Android platform team +- Performance degradation from excessive recomposition in complex UI hierarchies + Mitigation: Use remember, derivedStateOf, and key() appropriately, profile with Compose Layout Inspector, follow Compose performance best practices + Owner: Engineering team +- Developer knowledge gap leading to anti-patterns or misuse of Composable functions + Mitigation: Provide Compose training, establish code review guidelines, create internal documentation and examples + Owner: Engineering team and tech leads + +## Implementation Notes + +- Import androidx.compose.runtime.Composable explicitly in all UI component files +- Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives +- Integrate androidx.compose.runtime.remember for state that should survive recomposition +- Follow naming convention of PascalCase for Composable functions to distinguish from regular functions +- Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l +- grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l +- find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation (verify via static analysis or code review) + +## Enforcement + +- Verified by: Automated static analysis via Compose compiler checks during build +- Verified by: Code review checklist requiring @Composable annotation for UI functions +- Verified by: CI pipeline grep verification counting @Composable usage in UI packages +- Violation handling: Build failure if Composable functions violate compiler constraints (e.g., calling composables from non-composable context) +- Violation handling: Code review rejection for UI functions missing @Composable annotation +- Violation handling: Automated linting warnings for missing androidx.compose.runtime.Composable imports +- Exception process: Submit exception request to architecture team with justification for non-Compose UI approach +- Exception process: Document legacy View system usage in migration tracking system +- Exception process: Obtain approval from tech lead for interop scenarios requiring AndroidView wrappers \ No newline at end of file diff --git a/docs/adr/2b73f914-73c9-44f2-be05-509c1b7eb734-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md b/docs/adr/2b73f914-73c9-44f2-be05-509c1b7eb734-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md new file mode 100644 index 00000000000..5f726025e9e --- /dev/null +++ b/docs/adr/2b73f914-73c9-44f2-be05-509c1b7eb734-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Classes Implement + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. MUST: Test classes MUST implement setUp method to initialize test fixtures, file paths, and resource state before each test execution + +## Policy Block + +- MUST Test classes MUST implement setUp method to initialize test fixtures, file paths, and resource state before each test execution + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/2c48296f-6f1b-484f-a794-3d4af770e641-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-requiring-dependency.md b/docs/adr/2c48296f-6f1b-484f-a794-3d4af770e641-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-requiring-dependency.md new file mode 100644 index 00000000000..e05fd35a554 --- /dev/null +++ b/docs/adr/2c48296f-6f1b-484f-a794-3d4af770e641-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-requiring-dependency.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Requiring Dependency + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. MUST: Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint to enable Hilt code generation and injection lifecycle + +## Policy Block + +- MUST Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint to enable Hilt code generation and injection lifecycle + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/2d663395-aff0-4638-b8ed-0ade254d9757-adopt-zod-schema-validation-for-tool-input-parameters-numeric-coordinate-parameters.md b/docs/adr/2d663395-aff0-4638-b8ed-0ade254d9757-adopt-zod-schema-validation-for-tool-input-parameters-numeric-coordinate-parameters.md new file mode 100644 index 00000000000..658da33ec45 --- /dev/null +++ b/docs/adr/2d663395-aff0-4638-b8ed-0ade254d9757-adopt-zod-schema-validation-for-tool-input-parameters-numeric-coordinate-parameters.md @@ -0,0 +1,116 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Numeric Coordinate Parameters + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the Android Device Server MCP that accept external input parameters. + +## Context + +- The Android Device Server MCP exposes tool handlers that accept external input from clients, requiring validation to prevent invalid operations and runtime errors +- Tool parameters include coordinates, timing values, and boolean flags that must conform to specific constraints (non-negative integers, minimum values, type safety) +- The codebase imports 'zod' as a core dependency and '../utils/validation.js' across multiple tool implementations, indicating a standardized validation approach +- Two tool handlers (capture.ts and tap-at.ts) demonstrate consistent schema definition patterns using z.object() with typed field validators + +## Problem Statement + +Tool handlers in the Android Device Server MCP must validate external input parameters to ensure type safety, enforce domain constraints (e.g., non-negative coordinates, valid timing ranges), and prevent invalid ADB commands from being executed, but without a standardized validation approach, each tool would implement ad-hoc validation logic leading to inconsistency and maintenance burden. + +## Decision + +1. MUST: Numeric coordinate parameters (x, y) MUST be validated as non-negative integers using z.number().int().nonnegative() + +## Policy Block + +- MUST Numeric coordinate parameters (x, y) MUST be validated as non-negative integers using z.number().int().nonnegative() + +In scope: +- All tool handler implementations in src/tools/ that accept external parameters +- Input validation for ADB command parameters (coordinates, timing, flags) +- Public API contracts exposed through MCP tool interfaces + +Out of scope: +- Internal utility functions that do not accept external input +- ADB command output parsing and response formatting +- Device discovery and connection management logic + +## Rationale + +- The evidence shows consistent use of Zod schemas across capture.ts and tap-at.ts with identical import patterns ('zod', '../utils/validation.js'), indicating an established validation standard +- Schema definitions enforce domain-specific constraints (non-negative coordinates, minimum timing values) that prevent invalid ADB commands and improve system reliability +- Centralized validation through Zod provides type inference, runtime validation, and clear error messages, reducing boilerplate and improving developer experience +- The pattern appears in the security.input_validation facet with 91.20% confidence across 2 files, demonstrating measurable adoption + +## Consequences + +Positive: +- Type-safe input validation with automatic TypeScript type inference from schemas +- Consistent validation error messages and handling across all tool implementations +- Reduced boilerplate code compared to manual parameter checking and validation +- Clear API contracts that are self-documenting through schema definitions + +Negative: +- Additional runtime overhead for schema validation on every tool invocation +- Dependency on the Zod library increases bundle size and introduces external maintenance risk +- Developers must learn Zod API and schema composition patterns +- Schema definitions add verbosity to tool handler implementations + +## Alternatives + +- Manual parameter validation using TypeScript type guards and conditional checks (rejected) + Rejected because: Leads to inconsistent validation logic, verbose boilerplate, and no runtime type safety guarantees + When valid: For simple internal functions with minimal validation requirements +- Use JSON Schema with ajv validator for runtime validation (rejected) + Rejected because: Requires separate type definitions and schema definitions, losing TypeScript type inference benefits + When valid: When interoperating with systems that already use JSON Schema standards +- Use io-ts for functional programming style validation (rejected) + Rejected because: Steeper learning curve and more verbose syntax compared to Zod's developer-friendly API + When valid: In codebases with strong functional programming conventions using fp-ts + +## Risks + +- Zod library vulnerabilities or breaking changes in future versions could impact all tool handlers + Mitigation: Pin Zod version in package.json, monitor security advisories, and maintain comprehensive test coverage for validation logic + Owner: engineering team +- Complex nested schemas may introduce performance bottlenecks for high-frequency tool invocations + Mitigation: Profile validation performance, cache parsed schemas, and consider lazy validation for optional deep structures + Owner: engineering team +- Inconsistent schema patterns across tools if validation utilities are not properly documented + Mitigation: Document standard validation patterns in ../utils/validation.js, provide schema templates, and enforce through code review + Owner: engineering team + +## Implementation Notes + +- Import Zod and validation utilities at the top of each tool handler: import { z } from 'zod' and import validation utilities from '../utils/validation.js' +- Define the input schema as a const using z.object() with appropriate field validators before the handler function +- Use .int().nonnegative() for coordinate parameters, .min(0) for timing parameters, and .optional().default() for optional flags +- Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages +- Export the inferred TypeScript type using z.infer for use in function signatures and documentation + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "../utils/validation" .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool handlers in src/tools/ that accept external parameters import 'zod' and define validation schemas +- Grep commands show consistent usage of z.object() schema definitions across tool implementations +- Validation utility imports from '../utils/validation.js' are present in all relevant tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for new tool handlers +- Verified by: Automated grep-based checks in CI pipeline verifying presence of validation imports +- Verified by: TypeScript compilation ensuring type safety through schema inference +- Violation handling: Pull requests adding tool handlers without Zod validation are rejected during code review +- Violation handling: CI pipeline fails if tool files lack required validation imports +- Violation handling: Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation +- Exception process: Exceptions require written justification documenting why Zod validation is inappropriate for the specific use case +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in code comments with reference to approval decision \ No newline at end of file diff --git a/docs/adr/2d8fc4df-c881-4439-990d-de74ed8e0868-adopt-model-context-protocol-sdk-for-real-time-device-integration-server-instances-declare.md b/docs/adr/2d8fc4df-c881-4439-990d-de74ed8e0868-adopt-model-context-protocol-sdk-for-real-time-device-integration-server-instances-declare.md new file mode 100644 index 00000000000..cf022bcd9e9 --- /dev/null +++ b/docs/adr/2d8fc4df-c881-4439-990d-de74ed8e0868-adopt-model-context-protocol-sdk-for-real-time-device-integration-server-instances-declare.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Server Instances Declare + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. MUST: Server instances MUST declare capabilities at initialization time using the capabilities object structure + +## Policy Block + +- MUST Server instances MUST declare capabilities at initialization time using the capabilities object structure + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/2e0e51b9-ce85-493f-b4ee-423f63400418-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-operations-use.md b/docs/adr/2e0e51b9-ce85-493f-b4ee-423f63400418-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-operations-use.md new file mode 100644 index 00000000000..73190907895 --- /dev/null +++ b/docs/adr/2e0e51b9-ce85-493f-b4ee-423f63400418-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-operations-use.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Label Operations Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. SHOULD: Label operations SHOULD use set-based collection (.add, .remove) to ensure uniqueness and prevent duplicate label application + +## Policy Block + +- SHOULD Label operations SHOULD use set-based collection (.add, .remove) to ensure uniqueness and prevent duplicate label application + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/2e18e8d5-e460-4b7e-88a0-68d4f5d582b9-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-contracts-exported.md b/docs/adr/2e18e8d5-e460-4b7e-88a0-68d4f5d582b9-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-contracts-exported.md new file mode 100644 index 00000000000..917b4977ffd --- /dev/null +++ b/docs/adr/2e18e8d5-e460-4b7e-88a0-68d4f5d582b9-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-contracts-exported.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Public Contracts Exported + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. MUST: Public API contracts MUST be exported as named exports (e.g., capture, tapAt, FindElementResult, findElementWithObstruction) + +## Policy Block + +- MUST Public API contracts MUST be exported as named exports (e.g., capture, tapAt, FindElementResult, findElementWithObstruction) + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/2f3cbae9-8b64-4724-9f11-bd00c23c4653-adopt-zod-schema-validation-for-tool-input-parameters-boolean-flag-parameters.md b/docs/adr/2f3cbae9-8b64-4724-9f11-bd00c23c4653-adopt-zod-schema-validation-for-tool-input-parameters-boolean-flag-parameters.md new file mode 100644 index 00000000000..1dedb6a0d0e --- /dev/null +++ b/docs/adr/2f3cbae9-8b64-4724-9f11-bd00c23c4653-adopt-zod-schema-validation-for-tool-input-parameters-boolean-flag-parameters.md @@ -0,0 +1,116 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Boolean Flag Parameters + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the Android Device Server MCP that accept external input parameters. + +## Context + +- The Android Device Server MCP exposes tool handlers that accept external input from clients, requiring validation to prevent invalid operations and runtime errors +- Tool parameters include coordinates, timing values, and boolean flags that must conform to specific constraints (non-negative integers, minimum values, type safety) +- The codebase imports 'zod' as a core dependency and '../utils/validation.js' across multiple tool implementations, indicating a standardized validation approach +- Two tool handlers (capture.ts and tap-at.ts) demonstrate consistent schema definition patterns using z.object() with typed field validators + +## Problem Statement + +Tool handlers in the Android Device Server MCP must validate external input parameters to ensure type safety, enforce domain constraints (e.g., non-negative coordinates, valid timing ranges), and prevent invalid ADB commands from being executed, but without a standardized validation approach, each tool would implement ad-hoc validation logic leading to inconsistency and maintenance burden. + +## Decision + +1. SHOULD: Boolean flag parameters SHOULD use z.boolean().optional().default() to provide sensible defaults + +## Policy Block + +- SHOULD Boolean flag parameters SHOULD use z.boolean().optional().default() to provide sensible defaults + +In scope: +- All tool handler implementations in src/tools/ that accept external parameters +- Input validation for ADB command parameters (coordinates, timing, flags) +- Public API contracts exposed through MCP tool interfaces + +Out of scope: +- Internal utility functions that do not accept external input +- ADB command output parsing and response formatting +- Device discovery and connection management logic + +## Rationale + +- The evidence shows consistent use of Zod schemas across capture.ts and tap-at.ts with identical import patterns ('zod', '../utils/validation.js'), indicating an established validation standard +- Schema definitions enforce domain-specific constraints (non-negative coordinates, minimum timing values) that prevent invalid ADB commands and improve system reliability +- Centralized validation through Zod provides type inference, runtime validation, and clear error messages, reducing boilerplate and improving developer experience +- The pattern appears in the security.input_validation facet with 91.20% confidence across 2 files, demonstrating measurable adoption + +## Consequences + +Positive: +- Type-safe input validation with automatic TypeScript type inference from schemas +- Consistent validation error messages and handling across all tool implementations +- Reduced boilerplate code compared to manual parameter checking and validation +- Clear API contracts that are self-documenting through schema definitions + +Negative: +- Additional runtime overhead for schema validation on every tool invocation +- Dependency on the Zod library increases bundle size and introduces external maintenance risk +- Developers must learn Zod API and schema composition patterns +- Schema definitions add verbosity to tool handler implementations + +## Alternatives + +- Manual parameter validation using TypeScript type guards and conditional checks (rejected) + Rejected because: Leads to inconsistent validation logic, verbose boilerplate, and no runtime type safety guarantees + When valid: For simple internal functions with minimal validation requirements +- Use JSON Schema with ajv validator for runtime validation (rejected) + Rejected because: Requires separate type definitions and schema definitions, losing TypeScript type inference benefits + When valid: When interoperating with systems that already use JSON Schema standards +- Use io-ts for functional programming style validation (rejected) + Rejected because: Steeper learning curve and more verbose syntax compared to Zod's developer-friendly API + When valid: In codebases with strong functional programming conventions using fp-ts + +## Risks + +- Zod library vulnerabilities or breaking changes in future versions could impact all tool handlers + Mitigation: Pin Zod version in package.json, monitor security advisories, and maintain comprehensive test coverage for validation logic + Owner: engineering team +- Complex nested schemas may introduce performance bottlenecks for high-frequency tool invocations + Mitigation: Profile validation performance, cache parsed schemas, and consider lazy validation for optional deep structures + Owner: engineering team +- Inconsistent schema patterns across tools if validation utilities are not properly documented + Mitigation: Document standard validation patterns in ../utils/validation.js, provide schema templates, and enforce through code review + Owner: engineering team + +## Implementation Notes + +- Import Zod and validation utilities at the top of each tool handler: import { z } from 'zod' and import validation utilities from '../utils/validation.js' +- Define the input schema as a const using z.object() with appropriate field validators before the handler function +- Use .int().nonnegative() for coordinate parameters, .min(0) for timing parameters, and .optional().default() for optional flags +- Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages +- Export the inferred TypeScript type using z.infer for use in function signatures and documentation + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "../utils/validation" .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool handlers in src/tools/ that accept external parameters import 'zod' and define validation schemas +- Grep commands show consistent usage of z.object() schema definitions across tool implementations +- Validation utility imports from '../utils/validation.js' are present in all relevant tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for new tool handlers +- Verified by: Automated grep-based checks in CI pipeline verifying presence of validation imports +- Verified by: TypeScript compilation ensuring type safety through schema inference +- Violation handling: Pull requests adding tool handlers without Zod validation are rejected during code review +- Violation handling: CI pipeline fails if tool files lack required validation imports +- Violation handling: Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation +- Exception process: Exceptions require written justification documenting why Zod validation is inappropriate for the specific use case +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in code comments with reference to approval decision \ No newline at end of file diff --git a/docs/adr/2f7ee62b-4dfb-485a-8c08-8718131a2325-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-modules-use.md b/docs/adr/2f7ee62b-4dfb-485a-8c08-8718131a2325-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-modules-use.md new file mode 100644 index 00000000000..76955f3f550 --- /dev/null +++ b/docs/adr/2f7ee62b-4dfb-485a-8c08-8718131a2325-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-modules-use.md @@ -0,0 +1,117 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Library Modules Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Library modules in both TypeScript (android-device-server) and Kotlin (bitwarden network layer) implement error logging using platform-native error reporting mechanisms +- The TypeScript implementation uses console.error for tool errors and fatal errors in an MCP server context, while the Kotlin implementation uses Response.error with HTTP status codes and JSON-formatted error messages +- Both implementations integrate error logging within core library functionality, suggesting a cross-platform pattern for observable error handling in modular architectures +- The pattern appears in libraries that serve as integration points: an Android device MCP server and a network layer for API communication + +## Problem Statement + +Library modules require consistent, observable error logging mechanisms that integrate with their respective runtime environments (Node.js console for TypeScript, Retrofit Response for Kotlin) to enable debugging, monitoring, and error propagation without introducing external logging framework dependencies. + +## Decision + +1. MUST: Library modules MUST use platform-native error logging mechanisms (console.error for TypeScript/Node.js, Response.error for Kotlin/Retrofit) rather than introducing external logging framework dependencies + +## Policy Block + +- MUST Library modules MUST use platform-native error logging mechanisms (console.error for TypeScript/Node.js, Response.error for Kotlin/Retrofit) rather than introducing external logging framework dependencies + +In scope: +- TypeScript libraries running in Node.js environments with console API access +- Kotlin libraries using Retrofit for HTTP client functionality +- Library modules designed for reuse across multiple applications or services +- Error handling code paths within library boundaries + +Out of scope: +- Application-level logging infrastructure and aggregation systems +- Structured logging frameworks (Winston, Log4j, SLF4J) used by consuming applications +- Production monitoring and alerting systems external to library code +- Log persistence, rotation, or archival mechanisms + +Exceptions: +- EXC-001: Library is explicitly designed as a logging abstraction or wrapper (e.g., a logging facade library) +- EXC-002: Library operates in an environment without platform-native error logging (embedded systems, constrained runtimes) + +## Rationale + +- Platform-native error logging mechanisms (console.error, Response.error) are universally available in their respective runtime environments, eliminating external dependencies and reducing library footprint +- The pattern observed across TypeScript and Kotlin implementations demonstrates a cross-platform architectural principle: libraries should use runtime-provided error reporting rather than introducing framework coupling +- Using platform-native mechanisms enables library consumers to intercept, redirect, or enhance error logging through standard runtime hooks (console redirection, Retrofit interceptors) without modifying library code +- The evidence shows consistent integration of error logging with core library operations (tool execution, HTTP response construction), indicating error observability is treated as a first-class concern in library design + +## Consequences + +Positive: +- Reduced library dependency footprint by avoiding external logging framework dependencies +- Improved library portability across different application contexts and deployment environments +- Simplified library testing through standard console/response mocking mechanisms +- Enhanced consumer flexibility to integrate library error logging with application-specific monitoring infrastructure + +Negative: +- Limited structured logging capabilities compared to dedicated logging frameworks (no log levels, structured fields, or filtering) +- Potential inconsistency in error log format across different libraries and platforms +- Reduced observability features such as automatic context propagation, correlation IDs, or distributed tracing integration +- Console.error output may be difficult to parse or aggregate in production monitoring systems without additional tooling + +## Alternatives + +- Adopt a lightweight, cross-platform logging abstraction library (e.g., pino for TypeScript, SLF4J for Kotlin) as a standard dependency (rejected) + Rejected because: Introduces external dependency and version management complexity; conflicts with the observed pattern of using platform-native mechanisms; reduces library portability + When valid: When libraries require structured logging with log levels, filtering, and production-grade observability features that justify the dependency cost +- Implement custom logging abstraction within each library with pluggable backends (rejected) + Rejected because: Increases library code complexity and maintenance burden; duplicates logging abstraction logic across libraries; evidence shows preference for simple, direct error reporting + When valid: When building a library ecosystem with shared logging requirements and centralized logging infrastructure management +- Provide optional logging callback parameters for all error-prone operations (deferred) + Rejected because: Not observed in current evidence; would require API design changes across library interfaces + When valid: As an enhancement to enable custom error handling while maintaining platform-native defaults (see R-20-006) + +## Risks + +- Inconsistent error log formats across libraries make centralized monitoring and alerting difficult to implement + Mitigation: Establish error message format conventions (e.g., prefix patterns, JSON structure) documented in library development guidelines; provide examples of log parsing patterns for common monitoring tools + Owner: Engineering team, library maintainers +- Platform-native error logging may not provide sufficient detail for debugging complex library interactions in production + Mitigation: Ensure error messages include actionable context (operation name, input parameters, error codes); document error scenarios and troubleshooting steps in library documentation; consider optional verbose logging modes + Owner: Engineering team +- Console.error output in high-throughput scenarios may impact performance or overwhelm log aggregation systems + Mitigation: Implement error rate limiting or sampling for repetitive errors; document expected error logging volume in library performance characteristics; provide guidance on console redirection for production environments + Owner: Engineering team, SRE team + +## Implementation Notes + +- For TypeScript libraries, use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin network libraries using Retrofit, construct Response.error with appropriate HTTP status codes (e.g., HTTP_CODE_BAD_REQUEST) and JSON-formatted error messages using ResponseBody.Companion.toResponseBody +- Include sufficient context in error messages to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes +- Document expected error log output format and examples in library README to help consumers implement log parsing and monitoring + +## Continuation Context + + +Verify commands: +- grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" +- grep -r "Response\.error" --include="*.kt" src/ | head -20 +- grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l + +Accept when: +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + +## Enforcement + +- Verified by: Code review checklist verifying use of platform-native error logging mechanisms +- Verified by: Dependency analysis in CI pipeline flagging external logging framework dependencies in library modules +- Verified by: Grep-based verification commands checking for console.error and Response.error patterns in library code +- Violation handling: Code review feedback requesting removal of external logging framework dependencies and migration to platform-native mechanisms +- Violation handling: CI pipeline warnings when external logging dependencies are detected in library package manifests +- Violation handling: Architecture review required for libraries that cannot use platform-native error logging due to runtime constraints +- Exception process: Submit exception request documenting runtime environment constraints or logging requirements that cannot be met with platform-native mechanisms +- Exception process: Technical lead or architecture review approval required for exception +- Exception process: Document approved exceptions in library README with justification and alternative error reporting mechanism details \ No newline at end of file diff --git a/docs/adr/2f80d513-9981-40a9-b1ad-18f2cd79a59b-adopt-model-context-protocol-sdk-for-real-time-device-integration-tool-based-integrations.md b/docs/adr/2f80d513-9981-40a9-b1ad-18f2cd79a59b-adopt-model-context-protocol-sdk-for-real-time-device-integration-tool-based-integrations.md new file mode 100644 index 00000000000..c1f4d53f1a0 --- /dev/null +++ b/docs/adr/2f80d513-9981-40a9-b1ad-18f2cd79a59b-adopt-model-context-protocol-sdk-for-real-time-device-integration-tool-based-integrations.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Tool Based Integrations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. MUST: Tool-based integrations MUST implement runtime tool lookup using collection search patterns (tools.find) to resolve tool names to handlers + +## Policy Block + +- MUST Tool-based integrations MUST implement runtime tool lookup using collection search patterns (tools.find) to resolve tool names to handlers + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/2f964d88-ec51-4f7f-82a0-79bd1246932b-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-numeric-inputs-representing.md b/docs/adr/2f964d88-ec51-4f7f-82a0-79bd1246932b-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-numeric-inputs-representing.md new file mode 100644 index 00000000000..7e68237c9da --- /dev/null +++ b/docs/adr/2f964d88-ec51-4f7f-82a0-79bd1246932b-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-numeric-inputs-representing.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Numeric Inputs Representing + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. MUST: Numeric inputs representing coordinates or indices MUST be validated as non-negative integers using z.number().int().nonnegative() or equivalent constraints + +## Policy Block + +- MUST Numeric inputs representing coordinates or indices MUST be validated as non-negative integers using z.number().int().nonnegative() or equivalent constraints + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/30332d55-ad46-4c91-b4a2-e7c1a79f37a0-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-invoke.md b/docs/adr/30332d55-ad46-4c91-b4a2-e7c1a79f37a0-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-invoke.md new file mode 100644 index 00000000000..5df3321760c --- /dev/null +++ b/docs/adr/30332d55-ad46-4c91-b4a2-e7c1a79f37a0-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-invoke.md @@ -0,0 +1,118 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Scripts That Invoke + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains internal API scripts that parse external configuration data using json.load and process command-line arguments via argparse +- Configuration-driven automation scripts interact with external systems (GitHub API via subprocess) and make decisions based on parsed JSON structures +- Input validation patterns are present in the form of dictionary key access with .get() methods and exception handling for json parsing errors +- The label-pr.py script demonstrates a pattern where untrusted input (PR titles, file paths, JSON configuration) flows through validation logic before triggering actions +- The pattern reflects a security-conscious approach to internal tooling where configuration parsing includes defensive programming practices + +## Problem Statement + +Internal API scripts that consume external configuration and interact with external systems require consistent input validation to prevent injection attacks, malformed data propagation, and runtime failures when processing untrusted or semi-trusted input sources. + +## Decision + +1. SHOULD: Scripts that invoke external processes via subprocess SHOULD sanitize or validate any user-controlled input before passing it to shell commands + +## Policy Block + +- SHOULD Scripts that invoke external processes via subprocess SHOULD sanitize or validate any user-controlled input before passing it to shell commands + +In scope: +- Python scripts in .github/scripts/ that parse JSON configuration +- Internal automation tools that interact with external APIs (GitHub, CI/CD systems) +- Configuration-driven label assignment and PR processing workflows +- Scripts that use argparse, json.load, or subprocess modules + +Out of scope: +- Public-facing API endpoints with dedicated web frameworks +- Database query parameter validation (covered by separate ORM/query builder policies) +- Frontend form validation logic +- Third-party library internal validation + +Exceptions: +- EXC-001: Prototype or proof-of-concept scripts in development branches that are not merged to main +- EXC-002: Scripts that only process configuration files maintained exclusively by the core team with no external input + +## Rationale + +- The evidence shows a consistent pattern of defensive programming in label-pr.py using .get() methods for dictionary access and exception handling for JSON parsing, indicating an established practice worth codifying +- Internal automation scripts often bridge trusted configuration with untrusted external input (PR titles, file paths), creating a security boundary that requires explicit validation +- The use of argparse demonstrates structured input handling that prevents common injection vulnerabilities compared to raw sys.argv parsing +- Codifying this pattern reduces the risk of security vulnerabilities in internal tooling that could be exploited to manipulate CI/CD pipelines or access control systems + +## Consequences + +Positive: +- Reduced risk of injection attacks and malformed data propagation in internal automation scripts +- Consistent error handling improves debuggability and reduces runtime failures in CI/CD pipelines +- Structured argument parsing with argparse provides built-in help documentation and type validation +- Defensive dictionary access patterns prevent KeyError exceptions and improve script resilience + +Negative: +- Additional validation code increases initial development time for internal scripts +- Exception handling and safe access patterns add modest runtime overhead +- May create false sense of security if validation is incomplete or bypassed in edge cases +- Requires ongoing developer education to maintain validation practices across the team + +## Alternatives + +- Use JSON Schema validation libraries (jsonschema, pydantic) for comprehensive configuration validation (deferred) + Rejected because: null + When valid: Consider for complex configuration structures with nested objects and strict type requirements; current evidence shows simpler validation patterns are sufficient for existing use cases +- Rely on implicit Python exception handling without explicit try-except blocks (rejected) + Rejected because: Implicit exception handling provides poor error messages and makes debugging difficult; the evidence shows explicit exception handling is already practiced + When valid: Never valid for production internal APIs +- Use direct sys.argv parsing instead of argparse (rejected) + Rejected because: Direct sys.argv parsing is error-prone, lacks built-in validation, and provides no automatic help documentation; argparse is already in use and provides superior developer experience + When valid: Only acceptable for trivial single-argument scripts with no validation requirements + +## Risks + +- Incomplete validation coverage may leave security gaps if developers only validate some input paths + Mitigation: Establish code review checklist for input validation; use static analysis tools to detect unvalidated input flows + Owner: Engineering team and security reviewers +- Validation logic may become outdated as configuration schemas evolve + Mitigation: Document configuration schema alongside validation code; include validation tests in CI pipeline + Owner: Script maintainers +- Overly strict validation may break existing workflows or prevent legitimate use cases + Mitigation: Implement validation incrementally with clear error messages; provide exception process for legitimate edge cases + Owner: Engineering team + +## Implementation Notes + +- Add try-except blocks around json.load() calls with specific exception handling for JSONDecodeError to provide clear error messages +- Replace direct dictionary key access (config['key']) with safe access patterns (config.get('key', default_value)) throughout internal scripts +- Use argparse.ArgumentParser for all command-line argument parsing with explicit type specifications and help text +- Document expected configuration schema in script docstrings or adjacent README files to guide validation implementation + +## Continuation Context + + +Verify commands: +- grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' +- grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 +- find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l + +Accept when: +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries + +## Enforcement + +- Verified by: Code review checklist includes input validation verification for internal API scripts +- Verified by: Static analysis tools (pylint, bandit) configured to flag unsafe dictionary access and missing exception handling +- Verified by: CI pipeline includes grep-based validation checks for common input validation patterns +- Violation handling: Code review feedback requests addition of validation before approval +- Violation handling: CI warnings for detected validation gaps (non-blocking initially, blocking after grace period) +- Violation handling: Security review required for scripts that interact with external systems or process untrusted input +- Exception process: Developer documents the trust boundary and justification in PR description +- Exception process: Tech lead or security reviewer approves exception with explicit acknowledgment of risk +- Exception process: Exception is documented in script header comments with EXC-ID reference and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/341a988b-b32d-469a-a0ff-70671c52b46d-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-files-import.md b/docs/adr/341a988b-b32d-469a-a0ff-70671c52b46d-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-files-import.md new file mode 100644 index 00000000000..4cd169b9fc5 --- /dev/null +++ b/docs/adr/341a988b-b32d-469a-a0ff-70671c52b46d-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-files-import.md @@ -0,0 +1,123 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Composable Files Import + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all UI component development in the Android application codebase. + +## Context + +- The Android application uses Jetpack Compose as the declarative UI framework, requiring the @Composable annotation to mark functions that emit UI elements +- Three screen implementation files in the auth feature module (SetupUnlockScreen.kt, ExpiredRegistrationLinkScreen.kt, CompleteRegistrationHandler.kt) consistently use @Composable functions with androidx.compose.* foundation and runtime libraries +- The codebase demonstrates a pattern of composing UI hierarchies using androidx.compose.foundation.layout components (Column, Row, Spacer) and androidx.compose.runtime utilities (remember, Composable) +- The detection spans authentication-related UI screens, indicating organization-wide adoption of Compose for user-facing interface construction + +## Problem Statement + +Android UI development requires a consistent framework for declaring composable UI components that integrate with the Jetpack Compose runtime, ensuring proper recomposition behavior, state management, and layout composition across all screen implementations. + +## Decision + +1. MUST: Composable UI files MUST import androidx.compose.runtime.Composable explicitly rather than relying on wildcard imports + +## Policy Block + +- MUST Composable UI files MUST import androidx.compose.runtime.Composable explicitly rather than relying on wildcard imports + +In scope: +- All Android UI screen implementations in app/src/main/kotlin UI packages +- Authentication feature module UI components +- Any function that directly or indirectly emits Compose UI elements +- Handler components that coordinate UI composition with ViewModels + +Out of scope: +- ViewModel classes and business logic layers +- Data repository and network layer implementations +- Utility functions that do not emit UI +- Android View system components (legacy XML-based UI) +- Unit test files and test utilities + +Exceptions: +- EXC-001: Interoperating with legacy Android View system components during migration +- EXC-002: Preview functions for Android Studio Compose preview tooling + +## Rationale + +- Evidence from 3 files shows consistent use of @Composable annotation with 92.50% confidence, indicating established organizational practice +- Jetpack Compose provides declarative UI construction with automatic recomposition, reducing boilerplate and state synchronization complexity compared to imperative View system +- The androidx.compose.foundation and androidx.compose.runtime libraries form the core dependency set observed across all detected files, establishing a stable API surface +- Standardizing on @Composable annotation ensures compile-time verification of composable function constraints and enables Compose compiler optimizations + +## Consequences + +Positive: +- Declarative UI composition reduces state management complexity and eliminates manual view updates +- Compose compiler enforces composable function constraints at compile-time, catching errors early +- Consistent use of androidx.compose.* libraries provides a unified API surface for UI development +- Improved developer productivity through reduced boilerplate and better tooling support (preview, inspection) + +Negative: +- Requires learning curve for developers familiar with traditional Android View system +- Increases APK size due to Compose runtime library dependencies +- Limited interoperability with legacy View-based components requires AndroidView wrappers +- Compose compiler plugin adds build time overhead for annotation processing + +## Alternatives + +- Continue using traditional Android View system with XML layouts and findViewById (rejected) + Rejected because: Imperative View system requires manual state synchronization, increases boilerplate, and lacks compile-time UI verification. Evidence shows organization has already committed to Compose. + When valid: Only for legacy modules not yet migrated or when specific View components have no Compose equivalent +- Adopt alternative declarative UI frameworks (Flutter, React Native) (rejected) + Rejected because: Would require complete platform rewrite and abandonment of native Android tooling. Evidence shows deep integration with androidx.compose.* libraries. + When valid: For new greenfield projects with cross-platform requirements from inception +- Hybrid approach mixing Compose and View system components (deferred) + Rejected because: Not rejected but deferred as a migration strategy. Evidence shows pure Compose adoption in detected files. + When valid: During migration period for legacy screens not yet converted to Compose + +## Risks + +- Compose API instability or breaking changes in androidx.compose.* libraries during version upgrades + Mitigation: Pin Compose library versions in dependency management, test thoroughly before upgrading, monitor Compose release notes + Owner: Android platform team +- Performance degradation from excessive recomposition in complex UI hierarchies + Mitigation: Use remember, derivedStateOf, and key() appropriately, profile with Compose Layout Inspector, follow Compose performance best practices + Owner: Engineering team +- Developer knowledge gap leading to anti-patterns or misuse of Composable functions + Mitigation: Provide Compose training, establish code review guidelines, create internal documentation and examples + Owner: Engineering team and tech leads + +## Implementation Notes + +- Import androidx.compose.runtime.Composable explicitly in all UI component files +- Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives +- Integrate androidx.compose.runtime.remember for state that should survive recomposition +- Follow naming convention of PascalCase for Composable functions to distinguish from regular functions +- Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l +- grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l +- find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation (verify via static analysis or code review) + +## Enforcement + +- Verified by: Automated static analysis via Compose compiler checks during build +- Verified by: Code review checklist requiring @Composable annotation for UI functions +- Verified by: CI pipeline grep verification counting @Composable usage in UI packages +- Violation handling: Build failure if Composable functions violate compiler constraints (e.g., calling composables from non-composable context) +- Violation handling: Code review rejection for UI functions missing @Composable annotation +- Violation handling: Automated linting warnings for missing androidx.compose.runtime.Composable imports +- Exception process: Submit exception request to architecture team with justification for non-Compose UI approach +- Exception process: Document legacy View system usage in migration tracking system +- Exception process: Obtain approval from tech lead for interop scenarios requiring AndroidView wrappers \ No newline at end of file diff --git a/docs/adr/34575625-c418-4842-8fcc-12beb0210e02-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-navigation-lifecycle-events.md b/docs/adr/34575625-c418-4842-8fcc-12beb0210e02-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-navigation-lifecycle-events.md new file mode 100644 index 00000000000..c48ba58cf08 --- /dev/null +++ b/docs/adr/34575625-c418-4842-8fcc-12beb0210e02-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-navigation-lifecycle-events.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Navigation Lifecycle Events + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. SHOULD: Navigation and lifecycle events SHOULD use androidx.activity.compose utilities (BackHandler) when applicable + +## Policy Block + +- SHOULD Navigation and lifecycle events SHOULD use androidx.activity.compose utilities (BackHandler) when applicable + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/34bbb099-aca5-4383-ac43-e7fa38bf8036-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-asynchronous-operations-execute.md b/docs/adr/34bbb099-aca5-4383-ac43-e7fa38bf8036-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-asynchronous-operations-execute.md new file mode 100644 index 00000000000..c8ce4afbcba --- /dev/null +++ b/docs/adr/34bbb099-aca5-4383-ac43-e7fa38bf8036-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-asynchronous-operations-execute.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Asynchronous Operations Execute + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. MUST: Asynchronous operations MUST execute within viewModelScope to ensure proper lifecycle management and cancellation + +## Policy Block + +- MUST Asynchronous operations MUST execute within viewModelScope to ensure proper lifecycle management and cancellation + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/34c6892b-f9fa-4878-af0e-1f5462016952-adopt-hilt-dependency-injection-for-android-application-components-dependency-injection-used.md b/docs/adr/34c6892b-f9fa-4878-af0e-1f5462016952-adopt-hilt-dependency-injection-for-android-application-components-dependency-injection-used.md new file mode 100644 index 00000000000..004f3632402 --- /dev/null +++ b/docs/adr/34c6892b-f9fa-4878-af0e-1f5462016952-adopt-hilt-dependency-injection-for-android-application-components-dependency-injection-used.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Dependency Injection Used + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. SHOULD: Dependency injection SHOULD be used for repositories, managers, and platform services across all feature modules + +## Policy Block + +- SHOULD Dependency injection SHOULD be used for repositories, managers, and platform services across all feature modules + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/3508da20-cca1-4896-bb22-11b5c9bc8431-adopt-model-context-protocol-sdk-for-real-time-device-integration-type-definitions-modelcontextprotocol.md b/docs/adr/3508da20-cca1-4896-bb22-11b5c9bc8431-adopt-model-context-protocol-sdk-for-real-time-device-integration-type-definitions-modelcontextprotocol.md new file mode 100644 index 00000000000..1021502939a --- /dev/null +++ b/docs/adr/3508da20-cca1-4896-bb22-11b5c9bc8431-adopt-model-context-protocol-sdk-for-real-time-device-integration-type-definitions-modelcontextprotocol.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Type Definitions Modelcontextprotocol + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. SHOULD: Type definitions from @modelcontextprotocol/sdk/types.js SHOULD be used to ensure protocol compliance + +## Policy Block + +- SHOULD Type definitions from @modelcontextprotocol/sdk/types.js SHOULD be used to ensure protocol compliance + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/3522412b-75d3-403a-b692-053f3c8cfd0e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-composables-use.md b/docs/adr/3522412b-75d3-403a-b692-053f3c8cfd0e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-composables-use.md new file mode 100644 index 00000000000..1daf5b38072 --- /dev/null +++ b/docs/adr/3522412b-75d3-403a-b692-053f3c8cfd0e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-composables-use.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Screen Composables Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. MUST: Screen composables MUST use androidx.compose.foundation.layout components (Column, Row, Spacer, fillMaxSize, fillMaxWidth) for layout structure + +## Policy Block + +- MUST Screen composables MUST use androidx.compose.foundation.layout components (Column, Row, Spacer, fillMaxSize, fillMaxWidth) for layout structure + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/369552b7-50d1-4a9f-967a-17aa9e99288f-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-lookup-operations.md b/docs/adr/369552b7-50d1-4a9f-967a-17aa9e99288f-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-lookup-operations.md new file mode 100644 index 00000000000..f9c3f4b257a --- /dev/null +++ b/docs/adr/369552b7-50d1-4a9f-967a-17aa9e99288f-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-lookup-operations.md @@ -0,0 +1,114 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Tool Lookup Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements an MCP (Model Context Protocol) server using @modelcontextprotocol/sdk/server/index.js and stdio.js for communication +- Error conditions arise from both tool execution failures and fatal server-level errors requiring distinct logging contexts +- The server manages multiple tools accessed via a find pattern (tools.find(t => t.name === name)) requiring tool-scoped error identification +- Console-based logging provides immediate visibility in stdio-based server environments without external logging infrastructure dependencies +- The realtime boundary pattern (new Server with capabilities) necessitates synchronous error reporting for operational visibility + +## Problem Statement + +MCP servers operating over stdio require immediate, context-aware error logging that distinguishes between tool-level failures and fatal server errors while maintaining compatibility with the stdio transport layer and enabling operators to diagnose issues without external logging infrastructure. + +## Decision + +1. SHOULD: Tool lookup operations using tools.find(t => t.name === name) SHOULD log errors when tool resolution fails + +## Policy Block + +- SHOULD Tool lookup operations using tools.find(t => t.name === name) SHOULD log errors when tool resolution fails + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within the server capabilities boundary +- Fatal error conditions that terminate server operation +- Stdio-based transport layer error reporting + +Out of scope: +- Application-level logging within tool implementations +- Structured logging to external aggregation systems +- Client-side error handling and logging +- Non-error informational or debug logging + +## Rationale + +- The evidence shows explicit console.error usage for both tool-scoped errors (with name interpolation) and fatal errors, establishing a consistent pattern for synchronous error visibility +- The stdio transport layer used by @modelcontextprotocol/sdk/server/stdio.js requires console-based logging as the primary mechanism for operator visibility without interfering with protocol messages +- The tools.find pattern for tool resolution creates a natural boundary for tool-scoped error context, enabling precise error attribution +- The realtime server boundary (new Server with capabilities) necessitates immediate error reporting to maintain operational visibility during concurrent tool execution + +## Consequences + +Positive: +- Immediate error visibility in stdio-based environments without external dependencies +- Clear distinction between tool-level and server-level failures through consistent prefixing +- Simplified debugging through tool name context in error messages +- Zero-latency error reporting suitable for fatal error scenarios + +Negative: +- Console-based logging lacks structured metadata for automated analysis or aggregation +- No built-in error correlation across multiple tool invocations or server instances +- Limited filtering and search capabilities compared to structured logging systems +- Potential stderr pollution in environments with high error rates + +## Alternatives + +- Adopt structured logging library (e.g., winston, pino) with JSON output (rejected) + Rejected because: Adds external dependency and complexity for stdio-based MCP servers where console.error provides sufficient immediate visibility; structured logging better suited for long-running services with aggregation infrastructure + When valid: When MCP server operates in containerized environment with log aggregation pipeline or requires correlation across distributed tool executions +- Implement custom error event emitter with pluggable handlers (rejected) + Rejected because: Introduces abstraction overhead and delayed error reporting incompatible with fatal error scenarios requiring immediate visibility before process termination + When valid: When multiple error handling strategies must coexist or when error handling requires asynchronous processing +- Use MCP protocol error responses exclusively without console logging (rejected) + Rejected because: Protocol-level error responses do not provide operator visibility for fatal server errors or debugging during development; console logging serves distinct operational monitoring purpose + When valid: When all error handling occurs at client level and server-side operational monitoring is handled through external process supervision + +## Risks + +- Console error output may interfere with MCP protocol messages on stderr if not properly separated by transport layer + Mitigation: Verify @modelcontextprotocol/sdk/server/stdio.js properly isolates protocol messages from stderr; implement integration tests validating protocol integrity with error logging + Owner: MCP server engineering team +- Lack of structured error metadata limits automated error analysis and alerting capabilities + Mitigation: Document error message formats for parsing; consider hybrid approach with optional structured logging for production deployments while maintaining console.error baseline + Owner: Observability team +- Tool name context in error messages depends on correct name parameter propagation through tool resolution + Mitigation: Implement validation ensuring tool name is captured before execution; add fallback error logging for tool resolution failures + Owner: MCP server engineering team + +## Implementation Notes + +- Wrap all tool execution in try-catch blocks that call console.error with 'Tool error ({name}):' prefix before propagating or handling errors +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) before process exit +- Ensure tool name is captured from tools.find(t => t.name === name) result before execution to guarantee availability in error context +- Consider adding error codes or categories as structured prefixes within console.error messages to enable basic parsing without full structured logging + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ + +Accept when: +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + +## Enforcement + +- Verified by: Code review checking for console.error usage in error handling paths +- Verified by: Integration tests validating error log output format and content +- Verified by: Grep-based verification commands in CI pipeline +- Violation handling: Code review rejection for error handling without console.error logging +- Violation handling: CI pipeline warnings for missing tool name context in error logs +- Violation handling: Post-incident review when operational errors lack sufficient logging context +- Exception process: Document rationale for alternative logging approach in code comments +- Exception process: Obtain approval from observability team for structured logging adoption +- Exception process: Update ADR with amendment describing exception scope and justification \ No newline at end of file diff --git a/docs/adr/37e9c4b9-11fc-4ddb-b1f8-9b38695ac6d0-adopt-hilt-dependency-injection-for-android-application-components-viewmodel-classes-annotated.md b/docs/adr/37e9c4b9-11fc-4ddb-b1f8-9b38695ac6d0-adopt-hilt-dependency-injection-for-android-application-components-viewmodel-classes-annotated.md new file mode 100644 index 00000000000..e646e8a4787 --- /dev/null +++ b/docs/adr/37e9c4b9-11fc-4ddb-b1f8-9b38695ac6d0-adopt-hilt-dependency-injection-for-android-application-components-viewmodel-classes-annotated.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Viewmodel Classes Annotated + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. MUST: All ViewModel classes MUST be annotated with @HiltViewModel to enable constructor injection and proper scoping + +## Policy Block + +- MUST All ViewModel classes MUST be annotated with @HiltViewModel to enable constructor injection and proper scoping + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/394dd45f-d4b2-4184-83e2-5fd2fdc2959f-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-servers-import.md b/docs/adr/394dd45f-d4b2-4184-83e2-5fd2fdc2959f-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-servers-import.md new file mode 100644 index 00000000000..f3265adaffa --- /dev/null +++ b/docs/adr/394dd45f-d4b2-4184-83e2-5fd2fdc2959f-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-servers-import.md @@ -0,0 +1,114 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Mcp Servers Import + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-mcp server implementation requires structured error reporting for tool execution failures and fatal errors +- The @modelcontextprotocol/sdk provides server infrastructure including server/index.js, server/stdio.js, and types.js modules for building MCP-compliant servers +- Console-based error logging is used for both tool-level errors (with tool name context) and fatal server errors +- The server operates in a real-time boundary context with tool discovery patterns using array find operations +- Error visibility is critical for debugging tool execution failures in the MCP server environment + +## Problem Statement + +MCP server implementations need consistent error logging that captures both tool-specific failures and fatal server errors while maintaining compatibility with the @modelcontextprotocol/sdk framework and stdio-based communication patterns. + +## Decision + +1. MUST: MCP servers MUST import from @modelcontextprotocol/sdk/server/index.js, @modelcontextprotocol/sdk/server/stdio.js, and @modelcontextprotocol/sdk/types.js + +## Policy Block + +- MUST MCP servers MUST import from @modelcontextprotocol/sdk/server/index.js, @modelcontextprotocol/sdk/server/stdio.js, and @modelcontextprotocol/sdk/types.js + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within MCP servers +- Fatal error reporting in server lifecycle +- stdio-based MCP server communication + +Out of scope: +- Client-side MCP implementations +- Structured logging frameworks (e.g., Winston, Bunyan) +- Application-level business logic logging +- Performance metrics or tracing + +## Rationale + +- The evidence shows consistent use of console.error for both tool-level and fatal errors, establishing a pattern for error visibility in MCP server contexts +- The @modelcontextprotocol/sdk provides the foundational server infrastructure, making it a core dependency for MCP server implementations +- Console-based logging aligns with stdio-based server communication patterns where structured logging frameworks might interfere with the protocol +- The pattern of including tool names in error messages provides essential context for debugging in a tool-discovery architecture + +## Consequences + +Positive: +- Simple, dependency-free error logging that works immediately without configuration +- Compatible with stdio-based MCP protocol communication without interference +- Clear error context through structured message formats including tool names +- Minimal overhead for error reporting in real-time server operations + +Negative: +- Console.error lacks structured logging capabilities (no log levels, filtering, or formatting) +- No built-in log aggregation or persistence mechanisms +- Limited observability compared to dedicated logging frameworks +- Difficult to implement log sampling or rate limiting for high-frequency errors + +## Alternatives + +- Use a structured logging framework like Winston or Pino (rejected) + Rejected because: Structured logging frameworks may interfere with stdio-based MCP protocol communication and add unnecessary dependencies for simple error reporting + When valid: When MCP servers require log aggregation, filtering, or integration with centralized logging systems +- Implement custom error handling without console output (rejected) + Rejected because: Silent error handling would eliminate visibility into tool failures and fatal errors, making debugging impossible + When valid: Never valid for server implementations requiring operational visibility +- Use process.stderr.write for direct stream writing (rejected) + Rejected because: Direct stream writing requires manual formatting and lacks the convenience of console.error while providing minimal benefit + When valid: When precise control over stderr buffering or formatting is required + +## Risks + +- Console.error output may interfere with MCP protocol messages on stdio if not properly separated + Mitigation: Ensure stderr is used for errors (console.error) while stdout is reserved for protocol messages + Owner: engineering team +- Lack of log levels makes it difficult to filter or prioritize errors in production + Mitigation: Use consistent message prefixes ('Tool error', 'Fatal error') to enable grep-based filtering + Owner: engineering team +- No log persistence means errors are lost if not captured by process supervisor + Mitigation: Deploy MCP servers with process managers that capture stderr (systemd, PM2, Docker logging) + Owner: operations team + +## Implementation Notes + +- Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities +- Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}' +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) +- Ensure the server uses stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr) + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +Accept when: +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure + +## Enforcement + +- Verified by: Code review checking for console.error usage patterns +- Verified by: Grep-based verification commands in CI pipeline +- Verified by: Runtime testing of error scenarios to verify stderr output +- Violation handling: Code review feedback requesting correction to standard error logging format +- Violation handling: CI pipeline warnings for missing or non-standard error logging +- Violation handling: Documentation updates to clarify error logging requirements +- Exception process: Request exception through architecture review for alternative logging approaches +- Exception process: Document rationale for deviation including technical constraints +- Exception process: Obtain approval from platform team before implementing alternative logging \ No newline at end of file diff --git a/docs/adr/39c6995b-ecab-4fe7-bea8-8c6d0f14d122-adopt-async-handler-pattern-for-tool-operations-input-validation-zod.md b/docs/adr/39c6995b-ecab-4fe7-bea8-8c6d0f14d122-adopt-async-handler-pattern-for-tool-operations-input-validation-zod.md new file mode 100644 index 00000000000..7eb392705a4 --- /dev/null +++ b/docs/adr/39c6995b-ecab-4fe7-bea8-8c6d0f14d122-adopt-async-handler-pattern-for-tool-operations-input-validation-zod.md @@ -0,0 +1,120 @@ +# Adopt Async Handler Pattern for Tool Operations: Input Validation Zod + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the android-device-server MCP service. + +## Context + +- The android-device-server MCP service implements multiple tool operations (capture, tap-at, find-element-pipeline) that interact with external Android Debug Bridge (adb) processes and file system operations +- Tool operations require coordination of asynchronous I/O including process execution, file reads/writes, and validation steps that cannot block the event loop +- Each tool exports a handler function that serves as the primary entry point for tool invocation, establishing a consistent interface pattern across the codebase +- The codebase uses Zod for input validation schemas and node:path/node:fs for file system operations, requiring async coordination between validation and execution phases + +## Problem Statement + +Tool operations in the android-device-server require a consistent concurrency model that coordinates asynchronous validation, external process execution, and file system operations without blocking the Node.js event loop, while maintaining a uniform interface pattern across all tool implementations. + +## Decision + +1. MUST: Input validation using Zod schemas MUST occur before handler execution begins + +## Policy Block + +- MUST Input validation using Zod schemas MUST occur before handler execution begins + +In scope: +- All tool implementations in the android-device-server/src/tools directory +- Handler functions that coordinate adb process execution +- Operations involving file system reads/writes via node:fs +- Tool entry points exported for MCP service consumption + +Out of scope: +- Utility functions that do not serve as tool entry points +- Synchronous helper functions for data transformation +- Type definitions and interface declarations +- Test harness and mock implementations + +Exceptions: +- EXC-001: Pure computational functions that perform synchronous transformations without I/O + +## Rationale + +- The evidence shows consistent use of async handler functions (capture, tapAt, findElementWithObstruction) across 3 tool implementations, indicating an established pattern for coordinating asynchronous operations +- All detected tools import adb utilities and validation modules, requiring async coordination between validation, process execution, and result handling +- The handler pattern provides a uniform interface for tool invocation while encapsulating the complexity of async I/O coordination with external processes and file systems +- Using async/await patterns prevents event loop blocking and enables proper error propagation in the Node.js runtime environment + +## Consequences + +Positive: +- Consistent interface pattern across all tool implementations improves code maintainability and developer onboarding +- Non-blocking async operations ensure the MCP service remains responsive during long-running adb operations +- Separation of validation and execution phases enables early input rejection before expensive I/O operations +- Async/await syntax provides clear error handling and control flow compared to callback-based patterns + +Negative: +- Async handler pattern adds complexity compared to synchronous implementations for simple operations +- Requires developers to understand Promise semantics and async/await error handling +- Potential for unhandled promise rejections if error handling is not properly implemented +- Debugging async call stacks can be more challenging than synchronous execution flows + +## Alternatives + +- Synchronous handler functions with blocking I/O operations (rejected) + Rejected because: Blocking I/O would freeze the Node.js event loop during adb process execution and file operations, making the service unresponsive to concurrent requests + When valid: Only appropriate for pure computational functions without I/O dependencies +- Callback-based asynchronous pattern using Node.js callback conventions (rejected) + Rejected because: Callback patterns lead to nested callback hell and more complex error handling compared to async/await syntax available in modern Node.js + When valid: Legacy codebases or when targeting very old Node.js versions without async/await support +- Event emitter pattern for tool operations (rejected) + Rejected because: Event emitters add unnecessary complexity for request-response tool operations that have clear start and end points + When valid: Appropriate for streaming operations or long-running processes with multiple intermediate events + +## Risks + +- Unhandled promise rejections in handler functions could crash the Node.js process or leave operations in inconsistent states + Mitigation: Implement comprehensive try-catch blocks in all async handlers and configure Node.js to log unhandled rejections. Add integration tests that verify error handling paths. + Owner: Engineering team +- Long-running adb operations could accumulate pending promises and exhaust memory if not properly managed + Mitigation: Implement timeouts for all adb operations and add monitoring for pending promise counts. Consider implementing operation queuing with concurrency limits. + Owner: Engineering team +- Inconsistent error handling patterns across handlers could lead to unpredictable failure modes + Mitigation: Establish standard error handling patterns and document them. Create shared error handling utilities that all handlers can use. + Owner: Engineering team + +## Implementation Notes + +- All new tool implementations should follow the pattern: export an async function that accepts validated parameters and returns a Promise of the operation result +- Use Zod schemas defined at module level for input validation, and validate before entering the async handler logic +- Import adb utilities and file system operations from their respective modules (../adb/adb.js, node:fs, node:path) and await their results +- Ensure all async handlers have proper error handling with try-catch blocks and meaningful error messages that include context about the failed operation + +## Continuation Context + + +Verify commands: +- grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + +## Enforcement + +- Verified by: Code review checklist requiring async handler pattern for new tools +- Verified by: ESLint rules detecting synchronous I/O operations in tool handlers +- Verified by: Integration tests verifying non-blocking behavior under concurrent load +- Violation handling: Code review rejection for synchronous I/O in handler functions +- Violation handling: CI pipeline failure on ESLint violations for blocking operations +- Violation handling: Automated comments on PRs identifying missing async/await patterns +- Exception process: Document exception rationale in ADR amendment or inline code comments +- Exception process: Obtain tech lead approval for synchronous operations in tool handlers +- Exception process: Add exception to ESLint configuration with justification comment \ No newline at end of file diff --git a/docs/adr/39de29ab-fa4d-44f9-be50-6358eb14ca5f-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-file-system-operations.md b/docs/adr/39de29ab-fa4d-44f9-be50-6358eb14ca5f-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-file-system-operations.md new file mode 100644 index 00000000000..c68d8b6ccfd --- /dev/null +++ b/docs/adr/39de29ab-fa4d-44f9-be50-6358eb14ca5f-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-file-system-operations.md @@ -0,0 +1,118 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: File System Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test specifications and automation scripts across the codebase demonstrate consistent patterns of importing core libraries (vitest, node:fs, node:path, argparse, json, sys, os) and performing data access operations using collection methods like find(), add(), and load(). +- The pattern emerges in three distinct contexts: TypeScript test files using vitest for parsing dumpsys output, Python scripts for GitHub PR labeling automation, and Python scripts for JSON validation, indicating a cross-language consistency in data access approaches. +- Data access patterns consistently involve in-memory collection operations (Set.add(), Array.find()) and file-based JSON loading (json.load(f)), suggesting a preference for simple, direct data manipulation over abstraction layers. +- The detection spans test frameworks (describe, it), standard library imports (node:fs, node:path, argparse, json, sys, os), and runtime libraries (vitest), indicating these are foundational dependencies for testing and automation workflows. + +## Problem Statement + +The codebase lacks explicit guidance on which core libraries and data access patterns should be used for test specifications and automation scripts, leading to potential inconsistency in how data is loaded, queried, and manipulated across different modules and languages. + +## Decision + +1. MUST: File system operations in Node.js test and automation scripts MUST use the node:fs and node:path core modules rather than third-party file system libraries. + +## Policy Block + +- MUST File system operations in Node.js test and automation scripts MUST use the node:fs and node:path core modules rather than third-party file system libraries. + +In scope: +- Test specification files (*.spec.ts, *.test.ts) +- Automation scripts in .github/scripts/ +- Validation and parsing utilities +- CI/CD pipeline scripts + +Out of scope: +- Production application code with complex query requirements +- Database access layers requiring ORM or query builders +- High-performance data processing pipelines +- Browser-based test runners (e.g., Playwright, Cypress) + +Exceptions: +- EXC-001: Performance profiling indicates native collection methods create bottlenecks in large dataset processing +- EXC-002: External API contracts require specific JSON schema validation libraries beyond standard json module capabilities + +## Rationale + +- The evidence shows consistent use of standard library modules across 3 files with 90.83% confidence, indicating an established pattern that minimizes external dependencies and reduces maintenance burden. +- Using native collection methods (find(), add()) and standard library JSON parsing provides predictable behavior, reduces bundle size, and eliminates version compatibility issues with third-party libraries. +- The pattern spans both TypeScript (vitest, node:fs, node:path) and Python (json, sys, os, argparse) contexts, demonstrating language-appropriate choices that align with ecosystem conventions. +- Direct data access patterns without abstraction layers are appropriate for the observed use cases (test parsing, label automation, JSON validation) where query complexity is low and transparency is valuable. + +## Consequences + +Positive: +- Reduced dependency footprint in test and automation scripts, minimizing security surface area and dependency update overhead +- Improved script portability and long-term maintainability by relying on stable standard library APIs rather than third-party package ecosystems +- Lower cognitive overhead for developers familiar with standard library APIs, reducing onboarding time for test and automation contributions +- Faster script execution and smaller bundle sizes due to elimination of unnecessary abstraction layers + +Negative: +- Limited query expressiveness for complex data access patterns, requiring manual predicate logic rather than declarative query syntax +- Potential code duplication if similar data access patterns are repeated across multiple scripts without shared utility functions +- Lack of type safety in Python json.load() operations without additional validation layers or schema enforcement +- Manual error handling required for file I/O and JSON parsing operations without framework-provided retry or validation mechanisms + +## Alternatives + +- Adopt lodash/underscore for collection operations and data manipulation in both TypeScript and Python scripts (rejected) + Rejected because: Evidence shows native methods (Array.find(), Set.add()) are sufficient for current use cases; adding lodash would increase bundle size and introduce unnecessary dependency without demonstrated performance or expressiveness benefits + When valid: Valid for scripts processing large datasets requiring complex transformations like groupBy, partition, or deep merging +- Use Pydantic or JSON Schema validators for structured JSON validation instead of raw json.load() (deferred) + Rejected because: Current validation scripts use simple duplicate detection and basic structure checks; schema validation libraries add complexity without clear evidence of validation requirements beyond basic parsing + When valid: Valid when external API contracts require strict schema enforcement or when validation error messages need to be user-facing +- Standardize on Jest instead of vitest for TypeScript test specifications (rejected) + Rejected because: Evidence explicitly shows vitest usage in test specifications; Jest would require migration effort and vitest provides faster execution with native ESM support + When valid: Valid for projects requiring Jest-specific ecosystem plugins or snapshot testing features not available in vitest + +## Risks + +- Scripts may grow complex enough that native collection methods become verbose and error-prone, leading to maintenance burden + Mitigation: Establish shared utility modules for common data access patterns; set complexity threshold (e.g., >3 nested loops) triggering refactor to query library + Owner: Engineering team +- Lack of schema validation in JSON loading may allow malformed data to propagate through automation pipelines, causing runtime failures + Mitigation: Add explicit validation checks after json.load() for critical fields; document expected JSON structure in script docstrings; consider schema validation for external data sources + Owner: DevOps and automation team +- Standard library file I/O patterns may not handle edge cases (encoding issues, large files, concurrent access) as robustly as specialized libraries + Mitigation: Document encoding assumptions (UTF-8) explicitly; add file size checks for large file handling; use file locking for concurrent access scenarios + Owner: Engineering team + +## Implementation Notes + +- Create shared utility modules for common patterns: parseJsonFile(), findInCollection(), addToSet() to reduce duplication while maintaining standard library usage +- Add ESLint/Pylint rules to flag imports of lodash, ramda, or other collection libraries in test and automation script directories +- Document standard library API patterns in developer guide with examples from existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) +- For new automation scripts, use existing scripts as templates to ensure consistency in import patterns and data access approaches + +## Continuation Context + + +Verify commands: +- grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l +- grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l +- grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l +- grep -r "\.find(\|.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +Accept when: +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts + +## Enforcement + +- Verified by: CI pipeline static analysis checking for prohibited third-party imports in test and automation script directories +- Verified by: Code review checklist item verifying standard library usage for new test specifications and automation scripts +- Verified by: Automated dependency audits flagging new dependencies in package.json or requirements.txt within scope directories +- Violation handling: CI build fails if prohibited imports (lodash, ramda, etc.) are detected in test or automation scripts +- Violation handling: Pull requests adding external dependencies to automation scripts require architecture review and explicit justification +- Violation handling: Existing violations are tracked in technical debt backlog with migration plan to standard library equivalents +- Exception process: Submit exception request to tech lead with performance benchmarks or capability gap analysis +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration criteria +- Exception process: Review exceptions quarterly to assess if standard library improvements or refactoring can eliminate the need \ No newline at end of file diff --git a/docs/adr/39f948de-aff4-47e6-95e7-0b3b2fb9fa9b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-implement-exception.md b/docs/adr/39f948de-aff4-47e6-95e7-0b3b2fb9fa9b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-implement-exception.md new file mode 100644 index 00000000000..06019943b89 --- /dev/null +++ b/docs/adr/39f948de-aff4-47e6-95e7-0b3b2fb9fa9b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-scripts-implement-exception.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Scripts Implement Exception + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. MUST: Scripts MUST implement exception handling for JSON parsing errors (except json) to gracefully handle malformed configuration + +## Policy Block + +- MUST Scripts MUST implement exception handling for JSON parsing errors (except json) to gracefully handle malformed configuration + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/3a62eecd-2793-47fe-8552-26629b08d87e-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-test-files.md b/docs/adr/3a62eecd-2793-47fe-8552-26629b08d87e-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-test-files.md new file mode 100644 index 00000000000..5bd350801dd --- /dev/null +++ b/docs/adr/3a62eecd-2793-47fe-8552-26629b08d87e-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-test-files.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Typescript Test Files + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. MUST: TypeScript test files MUST use vitest as the test framework with describe/it block structure for test organization + +## Policy Block + +- MUST TypeScript test files MUST use vitest as the test framework with describe/it block structure for test organization + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/3c4f6334-326e-4af0-9e52-4693d07d104f-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-include.md b/docs/adr/3c4f6334-326e-4af0-9e52-4693d07d104f-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-include.md new file mode 100644 index 00000000000..4da67e2a3d5 --- /dev/null +++ b/docs/adr/3c4f6334-326e-4af0-9e52-4693d07d104f-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-include.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Validation Schemas Include + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. MAY: Validation schemas MAY include constraints such as .int(), .nonnegative(), .min() to enforce domain-specific invariants + +## Policy Block + +- MAY Validation schemas MAY include constraints such as .int(), .nonnegative(), .min() to enforce domain-specific invariants + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/3caee969-a463-4602-a10a-a9d0ac8725fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-extend-baseviewmodel.md b/docs/adr/3caee969-a463-4602-a10a-a9d0ac8725fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-extend-baseviewmodel.md new file mode 100644 index 00000000000..f65fad3b703 --- /dev/null +++ b/docs/adr/3caee969-a463-4602-a10a-a9d0ac8725fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-extend-baseviewmodel.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Extend Baseviewmodel + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. SHOULD: ViewModels SHOULD extend BaseViewModel when common functionality is required across multiple ViewModels + +## Policy Block + +- SHOULD ViewModels SHOULD extend BaseViewModel when common functionality is required across multiple ViewModels + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/3cf8eb73-bea4-4643-86bf-b694273ab96b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-classes-implemented.md b/docs/adr/3cf8eb73-bea4-4643-86bf-b694273ab96b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-classes-implemented.md new file mode 100644 index 00000000000..9d536a75440 --- /dev/null +++ b/docs/adr/3cf8eb73-bea4-4643-86bf-b694273ab96b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-state-classes-implemented.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: State Classes Implemented + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. MUST: State classes MUST be implemented as Parcelable data classes to support state restoration via SavedStateHandle + +## Policy Block + +- MUST State classes MUST be implemented as Parcelable data classes to support state restoration via SavedStateHandle + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/3f096b2b-bdbd-4efe-8762-adb7c08e57f3-enforce-input-validation-for-internal-api-configuration-parsers-internal-functions-implement.md b/docs/adr/3f096b2b-bdbd-4efe-8762-adb7c08e57f3-enforce-input-validation-for-internal-api-configuration-parsers-internal-functions-implement.md new file mode 100644 index 00000000000..2f9f91ac818 --- /dev/null +++ b/docs/adr/3f096b2b-bdbd-4efe-8762-adb7c08e57f3-enforce-input-validation-for-internal-api-configuration-parsers-internal-functions-implement.md @@ -0,0 +1,118 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Internal Functions Implement + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains internal API scripts that parse external configuration data using json.load and process command-line arguments via argparse +- Configuration-driven automation scripts interact with external systems (GitHub API via subprocess) and make decisions based on parsed JSON structures +- Input validation patterns are present in the form of dictionary key access with .get() methods and exception handling for json parsing errors +- The label-pr.py script demonstrates a pattern where untrusted input (PR titles, file paths, JSON configuration) flows through validation logic before triggering actions +- The pattern reflects a security-conscious approach to internal tooling where configuration parsing includes defensive programming practices + +## Problem Statement + +Internal API scripts that consume external configuration and interact with external systems require consistent input validation to prevent injection attacks, malformed data propagation, and runtime failures when processing untrusted or semi-trusted input sources. + +## Decision + +1. MAY: Internal API functions MAY implement additional schema validation using JSON Schema or similar validation frameworks for complex configuration structures + +## Policy Block + +- MAY Internal API functions MAY implement additional schema validation using JSON Schema or similar validation frameworks for complex configuration structures + +In scope: +- Python scripts in .github/scripts/ that parse JSON configuration +- Internal automation tools that interact with external APIs (GitHub, CI/CD systems) +- Configuration-driven label assignment and PR processing workflows +- Scripts that use argparse, json.load, or subprocess modules + +Out of scope: +- Public-facing API endpoints with dedicated web frameworks +- Database query parameter validation (covered by separate ORM/query builder policies) +- Frontend form validation logic +- Third-party library internal validation + +Exceptions: +- EXC-001: Prototype or proof-of-concept scripts in development branches that are not merged to main +- EXC-002: Scripts that only process configuration files maintained exclusively by the core team with no external input + +## Rationale + +- The evidence shows a consistent pattern of defensive programming in label-pr.py using .get() methods for dictionary access and exception handling for JSON parsing, indicating an established practice worth codifying +- Internal automation scripts often bridge trusted configuration with untrusted external input (PR titles, file paths), creating a security boundary that requires explicit validation +- The use of argparse demonstrates structured input handling that prevents common injection vulnerabilities compared to raw sys.argv parsing +- Codifying this pattern reduces the risk of security vulnerabilities in internal tooling that could be exploited to manipulate CI/CD pipelines or access control systems + +## Consequences + +Positive: +- Reduced risk of injection attacks and malformed data propagation in internal automation scripts +- Consistent error handling improves debuggability and reduces runtime failures in CI/CD pipelines +- Structured argument parsing with argparse provides built-in help documentation and type validation +- Defensive dictionary access patterns prevent KeyError exceptions and improve script resilience + +Negative: +- Additional validation code increases initial development time for internal scripts +- Exception handling and safe access patterns add modest runtime overhead +- May create false sense of security if validation is incomplete or bypassed in edge cases +- Requires ongoing developer education to maintain validation practices across the team + +## Alternatives + +- Use JSON Schema validation libraries (jsonschema, pydantic) for comprehensive configuration validation (deferred) + Rejected because: null + When valid: Consider for complex configuration structures with nested objects and strict type requirements; current evidence shows simpler validation patterns are sufficient for existing use cases +- Rely on implicit Python exception handling without explicit try-except blocks (rejected) + Rejected because: Implicit exception handling provides poor error messages and makes debugging difficult; the evidence shows explicit exception handling is already practiced + When valid: Never valid for production internal APIs +- Use direct sys.argv parsing instead of argparse (rejected) + Rejected because: Direct sys.argv parsing is error-prone, lacks built-in validation, and provides no automatic help documentation; argparse is already in use and provides superior developer experience + When valid: Only acceptable for trivial single-argument scripts with no validation requirements + +## Risks + +- Incomplete validation coverage may leave security gaps if developers only validate some input paths + Mitigation: Establish code review checklist for input validation; use static analysis tools to detect unvalidated input flows + Owner: Engineering team and security reviewers +- Validation logic may become outdated as configuration schemas evolve + Mitigation: Document configuration schema alongside validation code; include validation tests in CI pipeline + Owner: Script maintainers +- Overly strict validation may break existing workflows or prevent legitimate use cases + Mitigation: Implement validation incrementally with clear error messages; provide exception process for legitimate edge cases + Owner: Engineering team + +## Implementation Notes + +- Add try-except blocks around json.load() calls with specific exception handling for JSONDecodeError to provide clear error messages +- Replace direct dictionary key access (config['key']) with safe access patterns (config.get('key', default_value)) throughout internal scripts +- Use argparse.ArgumentParser for all command-line argument parsing with explicit type specifications and help text +- Document expected configuration schema in script docstrings or adjacent README files to guide validation implementation + +## Continuation Context + + +Verify commands: +- grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' +- grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 +- find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l + +Accept when: +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries + +## Enforcement + +- Verified by: Code review checklist includes input validation verification for internal API scripts +- Verified by: Static analysis tools (pylint, bandit) configured to flag unsafe dictionary access and missing exception handling +- Verified by: CI pipeline includes grep-based validation checks for common input validation patterns +- Violation handling: Code review feedback requests addition of validation before approval +- Violation handling: CI warnings for detected validation gaps (non-blocking initially, blocking after grace period) +- Violation handling: Security review required for scripts that interact with external systems or process untrusted input +- Exception process: Developer documents the trust boundary and justification in PR description +- Exception process: Tech lead or security reviewer approves exception with explicit acknowledgment of risk +- Exception process: Exception is documented in script header comments with EXC-ID reference and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/3f881fc6-f60d-48ce-b59c-a30ae2333de4-standardize-collection-find-pattern-for-in-memory-data-queries-use-array-find.md b/docs/adr/3f881fc6-f60d-48ce-b59c-a30ae2333de4-standardize-collection-find-pattern-for-in-memory-data-queries-use-array-find.md new file mode 100644 index 00000000000..2ad083f848c --- /dev/null +++ b/docs/adr/3f881fc6-f60d-48ce-b59c-a30ae2333de4-standardize-collection-find-pattern-for-in-memory-data-queries-use-array-find.md @@ -0,0 +1,100 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Use Array Find + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase demonstrates consistent use of JavaScript/TypeScript Array.find() method for querying in-memory collections across test specifications and automation scripts +- Test files in android-device-server use .find() with predicate functions to locate specific window objects by name property from parsed dumpsys output +- Python automation scripts use Set.add() operations for label and package name collection, indicating a pattern of in-memory data accumulation and membership testing +- The pattern appears in both testing contexts (vitest test suites) and operational contexts (GitHub automation scripts, JSON validation utilities) + +## Problem Statement + +Teams need a consistent, predictable approach for querying in-memory data structures to locate specific elements by property matching, particularly when working with parsed system output, configuration data, and test fixtures. Without standardization, different query patterns emerge that reduce code readability and increase cognitive load when navigating between modules. + +## Decision + +1. SHOULD: Use Array.find() with predicate functions for locating single elements in JavaScript/TypeScript collections when searching by property equality + +## Policy Block + +- SHOULD Use Array.find() with predicate functions for locating single elements in JavaScript/TypeScript collections when searching by property equality + +## Rationale + +- The pattern is observed across 3 files with 90.83% confidence, demonstrating consistent adoption in both test infrastructure and operational automation +- Array.find() provides clear semantic intent for single-element lookup operations, improving code readability compared to manual iteration +- Set.add() operations in Python scripts demonstrate parallel pattern of using language-native collection operations for membership and uniqueness constraints +- The pattern aligns with functional programming principles and modern JavaScript/TypeScript idioms, reducing imperative boilerplate + +## Consequences + +Positive: +- Improved code readability through consistent use of declarative collection query methods +- Reduced cognitive load when navigating between test specifications and automation scripts +- Better alignment with modern JavaScript/TypeScript idioms and functional programming patterns +- Clearer semantic intent in data access operations, making code review and maintenance easier + +Negative: +- Developers unfamiliar with functional array methods may require additional training or documentation +- Predicate function overhead may introduce minor performance cost compared to manual iteration in performance-critical paths +- Pattern may not extend cleanly to languages without first-class function support or equivalent collection APIs + +## Alternatives + +- Use manual for-loop iteration with conditional breaks for element lookup (rejected) + Rejected because: Manual iteration increases boilerplate code and reduces semantic clarity compared to declarative Array.find() method + When valid: Performance-critical paths where predicate function overhead is measured and significant +- Use Array.filter() followed by index access [0] for single-element lookup (rejected) + Rejected because: Array.filter() processes entire collection even after match is found, introducing unnecessary performance overhead + When valid: When subsequent operations require the filtered array or multiple matches are possible +- Use Map or Object lookup with key-based access instead of predicate-based search (deferred) + Rejected because: null + When valid: When data structure can be pre-indexed by lookup key and multiple queries justify indexing overhead + +## Risks + +- Performance degradation in large collections if .find() is used in tight loops or performance-critical paths + Mitigation: Profile data access patterns and consider pre-indexing with Map/Object for frequently queried large collections + Owner: engineering team +- Inconsistent adoption across polyglot codebase where Python, JavaScript, and TypeScript have different collection APIs + Mitigation: Document language-specific equivalents (Python: next(filter()), JavaScript/TypeScript: Array.find()) in coding standards + Owner: engineering team +- Undefined return values from .find() may cause runtime errors if not properly handled with null checks + Mitigation: Enforce TypeScript strict null checks and require explicit undefined handling in code review + Owner: engineering team + +## Implementation Notes + +- Use TypeScript strict mode to enforce null/undefined handling for .find() return values +- Consider creating utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication +- Document the pattern in coding standards with examples from dumpsys.spec.ts showing window lookup by name property +- For Python code, use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find() + +## Continuation Context + + +Verify commands: +- grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . +- grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' +- npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' + +Accept when: +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + +## Enforcement + +- Verified by: Code review checklist includes verification of collection query patterns +- Verified by: ESLint rules configured to discourage manual iteration where Array methods are applicable +- Verified by: Test coverage requirements ensure query operations are tested with expected and missing elements +- Violation handling: Code review feedback requests refactoring of manual iteration to declarative collection methods +- Violation handling: ESLint warnings flagged in CI pipeline for review before merge +- Violation handling: Documentation links provided to developers during code review for pattern examples +- Exception process: Performance-critical paths may use manual iteration if profiling demonstrates measurable impact +- Exception process: Exception requests must include benchmark data comparing Array.find() vs manual iteration +- Exception process: Approved exceptions documented inline with comments explaining performance justification \ No newline at end of file diff --git a/docs/adr/40e0fe78-854d-4145-942b-c15fcae948ee-standardize-kotlinx-serialization-json-testing-with-type-discriminators-serialization-tests-use.md b/docs/adr/40e0fe78-854d-4145-942b-c15fcae948ee-standardize-kotlinx-serialization-json-testing-with-type-discriminators-serialization-tests-use.md new file mode 100644 index 00000000000..46b2d83b17e --- /dev/null +++ b/docs/adr/40e0fe78-854d-4145-942b-c15fcae948ee-standardize-kotlinx-serialization-json-testing-with-type-discriminators-serialization-tests-use.md @@ -0,0 +1,116 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Serialization Tests Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests validate JSON encoding/decoding behavior at service boundaries where data crosses module or API boundaries +- The codebase uses kotlinx.serialization for JSON serialization with custom serializers for domain models like WrappedAccountCryptographicState +- Type discriminators (e.g., 'v1', 'v2') enable versioned serialization formats to support backward compatibility and schema evolution +- Tests use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings +- The pattern appears in cryptographic state serialization and policy view conversion, indicating cross-cutting serialization concerns + +## Problem Statement + +Service boundaries require reliable serialization contracts that can evolve over time without breaking existing clients. Without standardized testing of JSON serialization including type discriminators and property mappings, schema changes may introduce silent data corruption or deserialization failures at runtime. + +## Decision + +1. MUST: Serialization tests MUST use buildJsonObject and assertEquals to verify exact JSON output including all properties + +## Policy Block + +- MUST Serialization tests MUST use buildJsonObject and assertEquals to verify exact JSON output including all properties + +In scope: +- Custom kotlinx.serialization serializers for domain models +- Extension functions converting between domain models and SDK types +- JSON encoding/decoding at service and module boundaries +- Versioned serialization formats using type discriminators + +Out of scope: +- Internal data transformations that do not cross serialization boundaries +- Third-party library serializers without custom logic +- Binary serialization formats +- Database entity mappings + +## Rationale + +- The evidence shows consistent use of kotlinx.serialization.json.buildJsonObject and assertEquals patterns across serialization tests, indicating an established testing approach +- Type discriminators ('v1', 'v2') in WrappedAccountCryptographicState tests demonstrate versioning requirements at cryptographic state boundaries +- Tests for toSdkPolicyViews extension function show validation of conversion logic between network models and SDK policy views +- The pattern appears in both data layer (cryptographic state) and vault repository (policy conversion), suggesting cross-cutting serialization concerns requiring standardized testing + +## Consequences + +Positive: +- Serialization contract changes are caught at test time rather than runtime, preventing data corruption +- Type discriminator validation ensures versioned schemas maintain backward compatibility +- Standardized test structure improves maintainability and makes serialization behavior explicit +- Extension function tests verify boundary conversions handle edge cases like empty lists + +Negative: +- Additional test code increases maintenance burden when serialization formats change +- Exact JSON structure assertions are brittle and may require updates for cosmetic changes +- Test duplication across similar serializers may occur without shared test utilities +- Mock factory functions add indirection that may obscure actual test data + +## Alternatives + +- Use property-based testing to verify serialization round-trips without asserting exact JSON structure (rejected) + Rejected because: Does not validate exact JSON contract including field names and discriminator values required for external API compatibility + When valid: Internal serialization where only round-trip fidelity matters, not exact wire format +- Generate serialization tests automatically from schema definitions (deferred) + Rejected because: Requires additional tooling and schema-first development approach not currently in place + When valid: When adopting schema-first API design with OpenAPI or JSON Schema definitions +- Rely on integration tests to catch serialization issues (rejected) + Rejected because: Integration tests are slower, less isolated, and provide poor feedback for serialization contract violations + When valid: Never as sole verification; integration tests complement but do not replace unit-level serialization tests + +## Risks + +- Brittle tests that break on benign JSON formatting changes (e.g., property order) + Mitigation: Use JSON comparison that ignores property order; consider semantic equality checks for non-critical formatting + Owner: engineering team +- Test coverage gaps for deserialization paths and error handling + Mitigation: Extend testing standard to include deserialization tests and malformed input handling + Owner: engineering team +- Type discriminator values may conflict across different serializers + Mitigation: Establish discriminator naming conventions and maintain registry of used discriminator values + Owner: architecture team + +## Implementation Notes + +- Create test classes in src/test/kotlin mirroring the package structure of serializers under test +- Use @Test annotation and assertEquals with buildJsonObject for exact JSON structure validation +- For versioned schemas, create separate test methods for each version verifying the type discriminator field +- When testing extension functions like toSdkPolicyViews, include edge cases such as empty lists and multi-item collections +- Consider extracting mock factory functions (e.g., createMockPolicy) to shared test utilities for reuse across test classes + +## Continuation Context + + +Verify commands: +- grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l +- find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +Accept when: +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + +## Enforcement + +- Verified by: Code review checklist requiring serialization tests for new serializers +- Verified by: CI pipeline test coverage reporting for serialization packages +- Verified by: Static analysis detecting serializers without corresponding test classes +- Violation handling: Pull requests adding serializers without tests are blocked in code review +- Violation handling: Coverage reports flag untested serialization code for remediation +- Violation handling: Architecture review required for serializers lacking discriminator validation +- Exception process: Exceptions require architecture team approval with documented justification +- Exception process: Temporary exceptions must include remediation plan and timeline +- Exception process: Exception requests must demonstrate why alternative testing approach provides equivalent contract validation \ No newline at end of file diff --git a/docs/adr/4258dbf5-ca5a-43b8-aec7-6ca64a00e937-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-combine-get.md b/docs/adr/4258dbf5-ca5a-43b8-aec7-6ca64a00e937-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-combine-get.md new file mode 100644 index 00000000000..44f0c3093b7 --- /dev/null +++ b/docs/adr/4258dbf5-ca5a-43b8-aec7-6ca64a00e937-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-combine-get.md @@ -0,0 +1,114 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Scripts Combine Get + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration scripts in .github/scripts/ interact with external APIs (JIRA, GitHub) where response structures may vary or contain optional fields +- Python's dictionary .get() method provides safe access to potentially missing keys without raising KeyError exceptions +- Two automation scripts (jira_release_notes.py, label-pr.py) demonstrate consistent use of .get() for accessing nested JSON response fields +- The pattern appears in CI/CD automation context where script failures would block workflows and require defensive programming + +## Problem Statement + +Integration scripts that parse external API responses need a consistent approach to handle optional or missing fields without causing runtime exceptions that would fail CI/CD workflows. Direct dictionary key access raises KeyError for missing keys, requiring explicit exception handling or key existence checks throughout the codebase. + +## Decision + +1. MAY: Scripts MAY combine .get() with explicit None checks when distinguishing between missing keys and null values is required + +## Policy Block + +- MAY Scripts MAY combine .get() with explicit None checks when distinguishing between missing keys and null values is required + +In scope: +- Python scripts in .github/scripts/ that parse JSON responses from external APIs +- Integration test utilities that process configuration files with optional fields +- Automation scripts that interact with GitHub API, JIRA API, or similar external services + +Out of scope: +- Internal data structures where key presence is guaranteed by construction +- Type-checked code using TypedDict or dataclasses where missing keys indicate programming errors +- Performance-critical paths where exception handling overhead is measured and acceptable + +Exceptions: +- EXC-001: API contract explicitly guarantees field presence and KeyError is preferred for contract violations + +## Rationale + +- The evidence shows consistent use of .get() across two independent scripts (jira_release_notes.py, label-pr.py) when accessing fields from external API responses, indicating an established pattern +- Using .get() prevents KeyError exceptions in CI/CD automation where script failures would block workflows and require manual intervention +- The pattern appears specifically in integration contexts (testing.integration facet) where external system responses are unpredictable +- Python's .get() method provides a concise, readable alternative to try-except blocks or explicit key existence checks + +## Consequences + +Positive: +- Reduced runtime exceptions in CI/CD workflows from missing or optional API response fields +- More resilient integration scripts that gracefully handle API schema variations +- Cleaner code without verbose try-except blocks or 'key in dict' checks +- Easier debugging with explicit default values visible at access points + +Negative: +- Silent failures possible if default values mask actual API errors or schema changes +- Potential confusion between missing keys (None) and explicit null values without additional checks +- May hide API contract violations that should be caught and reported +- Slightly less explicit than try-except blocks for documenting expected vs. exceptional cases + +## Alternatives + +- Use try-except blocks with KeyError handling for all dictionary access (rejected) + Rejected because: More verbose and reduces code readability; evidence shows .get() is preferred pattern in existing scripts + When valid: When explicit exception handling logic is needed or when distinguishing KeyError from other exceptions is important +- Use 'key in dict' checks before accessing each field (rejected) + Rejected because: Requires two dictionary lookups and increases code verbosity; .get() is more idiomatic Python + When valid: When the presence check itself needs to trigger different logic paths beyond default values +- Parse responses into typed dataclasses with validation (deferred) + Rejected because: Would require additional dependencies (pydantic, attrs) and refactoring; may be considered for future enhancement + When valid: For complex response schemas where full validation and type safety are required + +## Risks + +- API schema changes may go undetected if missing fields are silently handled with defaults + Mitigation: Log warnings when expected fields are missing; implement schema validation tests for critical API endpoints + Owner: Engineering team +- Inconsistent default value choices across scripts may lead to unexpected behavior + Mitigation: Document standard default values for common field types; review default choices in code review + Owner: Engineering team +- Overuse of .get() may mask programming errors in internal data structures + Mitigation: Limit .get() usage to external API boundaries as defined in policy scope; use direct access for internal structures + Owner: Engineering team + +## Implementation Notes + +- When accessing nested fields, use .get() with empty dict default for intermediate keys: response.get('fields', {}).get('field_name') +- Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling +- Add comments documenting why a field might be missing when using .get() for non-obvious cases +- Consider logging at debug level when .get() returns a default value to aid troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r '\.get(' .github/scripts/*.py | wc -l +- grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l +- python -m py_compile .github/scripts/*.py + +Accept when: +- Integration scripts in .github/scripts/ use .get() for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields + +## Enforcement + +- Verified by: Code review for new integration scripts +- Verified by: Grep-based verification in CI to detect bracket notation in API response handling +- Verified by: Runtime monitoring of CI/CD workflow failures +- Violation handling: Code review feedback requesting .get() usage for external API access +- Violation handling: CI workflow failures due to KeyError trigger review of dictionary access patterns +- Violation handling: Documentation updates if legitimate exceptions are identified +- Exception process: Document API contract guarantee in code comments +- Exception process: Obtain code review approval with explicit justification +- Exception process: Add to exception registry with EXC-001 reference \ No newline at end of file diff --git a/docs/adr/42ea08ba-ec5f-4deb-a4f5-082aba434692-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md b/docs/adr/42ea08ba-ec5f-4deb-a4f5-082aba434692-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md new file mode 100644 index 00000000000..154742de579 --- /dev/null +++ b/docs/adr/42ea08ba-ec5f-4deb-a4f5-082aba434692-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md @@ -0,0 +1,123 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Composable Functions Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all UI component development in the Android application codebase. + +## Context + +- The Android application uses Jetpack Compose as the declarative UI framework, requiring the @Composable annotation to mark functions that emit UI elements +- Three screen implementation files in the auth feature module (SetupUnlockScreen.kt, ExpiredRegistrationLinkScreen.kt, CompleteRegistrationHandler.kt) consistently use @Composable functions with androidx.compose.* foundation and runtime libraries +- The codebase demonstrates a pattern of composing UI hierarchies using androidx.compose.foundation.layout components (Column, Row, Spacer) and androidx.compose.runtime utilities (remember, Composable) +- The detection spans authentication-related UI screens, indicating organization-wide adoption of Compose for user-facing interface construction + +## Problem Statement + +Android UI development requires a consistent framework for declaring composable UI components that integrate with the Jetpack Compose runtime, ensuring proper recomposition behavior, state management, and layout composition across all screen implementations. + +## Decision + +1. SHOULD: Composable functions SHOULD use androidx.compose.runtime.remember for state preservation across recompositions + +## Policy Block + +- SHOULD Composable functions SHOULD use androidx.compose.runtime.remember for state preservation across recompositions + +In scope: +- All Android UI screen implementations in app/src/main/kotlin UI packages +- Authentication feature module UI components +- Any function that directly or indirectly emits Compose UI elements +- Handler components that coordinate UI composition with ViewModels + +Out of scope: +- ViewModel classes and business logic layers +- Data repository and network layer implementations +- Utility functions that do not emit UI +- Android View system components (legacy XML-based UI) +- Unit test files and test utilities + +Exceptions: +- EXC-001: Interoperating with legacy Android View system components during migration +- EXC-002: Preview functions for Android Studio Compose preview tooling + +## Rationale + +- Evidence from 3 files shows consistent use of @Composable annotation with 92.50% confidence, indicating established organizational practice +- Jetpack Compose provides declarative UI construction with automatic recomposition, reducing boilerplate and state synchronization complexity compared to imperative View system +- The androidx.compose.foundation and androidx.compose.runtime libraries form the core dependency set observed across all detected files, establishing a stable API surface +- Standardizing on @Composable annotation ensures compile-time verification of composable function constraints and enables Compose compiler optimizations + +## Consequences + +Positive: +- Declarative UI composition reduces state management complexity and eliminates manual view updates +- Compose compiler enforces composable function constraints at compile-time, catching errors early +- Consistent use of androidx.compose.* libraries provides a unified API surface for UI development +- Improved developer productivity through reduced boilerplate and better tooling support (preview, inspection) + +Negative: +- Requires learning curve for developers familiar with traditional Android View system +- Increases APK size due to Compose runtime library dependencies +- Limited interoperability with legacy View-based components requires AndroidView wrappers +- Compose compiler plugin adds build time overhead for annotation processing + +## Alternatives + +- Continue using traditional Android View system with XML layouts and findViewById (rejected) + Rejected because: Imperative View system requires manual state synchronization, increases boilerplate, and lacks compile-time UI verification. Evidence shows organization has already committed to Compose. + When valid: Only for legacy modules not yet migrated or when specific View components have no Compose equivalent +- Adopt alternative declarative UI frameworks (Flutter, React Native) (rejected) + Rejected because: Would require complete platform rewrite and abandonment of native Android tooling. Evidence shows deep integration with androidx.compose.* libraries. + When valid: For new greenfield projects with cross-platform requirements from inception +- Hybrid approach mixing Compose and View system components (deferred) + Rejected because: Not rejected but deferred as a migration strategy. Evidence shows pure Compose adoption in detected files. + When valid: During migration period for legacy screens not yet converted to Compose + +## Risks + +- Compose API instability or breaking changes in androidx.compose.* libraries during version upgrades + Mitigation: Pin Compose library versions in dependency management, test thoroughly before upgrading, monitor Compose release notes + Owner: Android platform team +- Performance degradation from excessive recomposition in complex UI hierarchies + Mitigation: Use remember, derivedStateOf, and key() appropriately, profile with Compose Layout Inspector, follow Compose performance best practices + Owner: Engineering team +- Developer knowledge gap leading to anti-patterns or misuse of Composable functions + Mitigation: Provide Compose training, establish code review guidelines, create internal documentation and examples + Owner: Engineering team and tech leads + +## Implementation Notes + +- Import androidx.compose.runtime.Composable explicitly in all UI component files +- Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives +- Integrate androidx.compose.runtime.remember for state that should survive recomposition +- Follow naming convention of PascalCase for Composable functions to distinguish from regular functions +- Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l +- grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l +- find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation (verify via static analysis or code review) + +## Enforcement + +- Verified by: Automated static analysis via Compose compiler checks during build +- Verified by: Code review checklist requiring @Composable annotation for UI functions +- Verified by: CI pipeline grep verification counting @Composable usage in UI packages +- Violation handling: Build failure if Composable functions violate compiler constraints (e.g., calling composables from non-composable context) +- Violation handling: Code review rejection for UI functions missing @Composable annotation +- Violation handling: Automated linting warnings for missing androidx.compose.runtime.Composable imports +- Exception process: Submit exception request to architecture team with justification for non-Compose UI approach +- Exception process: Document legacy View system usage in migration tracking system +- Exception process: Obtain approval from tech lead for interop scenarios requiring AndroidView wrappers \ No newline at end of file diff --git a/docs/adr/42f674c8-a883-4f57-862a-e52d9c7e217a-adopt-model-context-protocol-sdk-for-android-device-integration-mcp-server-implementations.md b/docs/adr/42f674c8-a883-4f57-862a-e52d9c7e217a-adopt-model-context-protocol-sdk-for-android-device-integration-mcp-server-implementations.md new file mode 100644 index 00000000000..75dae0f02f7 --- /dev/null +++ b/docs/adr/42f674c8-a883-4f57-862a-e52d9c7e217a-adopt-model-context-protocol-sdk-for-android-device-integration-mcp-server-implementations.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Mcp Server Implementations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. MUST: MCP server implementations MUST import @modelcontextprotocol/sdk/server/index.js for server construction + +## Policy Block + +- MUST MCP server implementations MUST import @modelcontextprotocol/sdk/server/index.js for server construction + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/43586977-155f-4fca-831c-ecd83c5f923f-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activity-implementations-override.md b/docs/adr/43586977-155f-4fca-831c-ecd83c5f923f-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activity-implementations-override.md new file mode 100644 index 00000000000..85d4d510e14 --- /dev/null +++ b/docs/adr/43586977-155f-4fca-831c-ecd83c5f923f-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activity-implementations-override.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activity Implementations Override + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. MUST: Activity implementations MUST override onCreate with Bundle parameter and handle Intent routing through android.content.Intent to support system-initiated flows + +## Policy Block + +- MUST Activity implementations MUST override onCreate with Bundle parameter and handle Intent routing through android.content.Intent to support system-initiated flows + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/442fb2a9-4d0e-4770-8b45-817b45829b74-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-application-entry-points.md b/docs/adr/442fb2a9-4d0e-4770-8b45-817b45829b74-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-application-entry-points.md new file mode 100644 index 00000000000..72ba8233f45 --- /dev/null +++ b/docs/adr/442fb2a9-4d0e-4770-8b45-817b45829b74-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-application-entry-points.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Application Entry Points + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. MUST: All application entry points MUST extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity to ensure compatibility with AndroidX lifecycle, ViewModel, and Compose integration + +## Policy Block + +- MUST All application entry points MUST extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity to ensure compatibility with AndroidX lifecycle, ViewModel, and Compose integration + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/45829dc1-79d0-4b6b-b98f-10f9cf88e1bf-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-android.md b/docs/adr/45829dc1-79d0-4b6b-b98f-10f9cf88e1bf-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-android.md new file mode 100644 index 00000000000..aa11bfee612 --- /dev/null +++ b/docs/adr/45829dc1-79d0-4b6b-b98f-10f9cf88e1bf-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-android.md @@ -0,0 +1,116 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Handling Android + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Three ViewModel implementations (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel) consistently use HiltViewModel annotation for dependency injection at public API boundaries handling Android Intent-based interactions +- All three ViewModels extend BaseViewModel and coordinate external API contracts through sealed action types (CredentialProviderAction, AuthCallbackAction) and data classes for Intent processing +- The pattern appears in ViewModels managing authentication flows, credential provider operations, and autofill callbacks, indicating a standardized approach to handling Android system integration points +- Dependencies injected include AuthRepository, BitwardenCredentialManager, and CredentialProviderRequestManager, suggesting a consistent architectural layer for external API coordination + +## Problem Statement + +Android ViewModels serving as public API boundaries for system integrations (credential providers, authentication callbacks, autofill) require consistent dependency injection to ensure testability, lifecycle management, and separation of concerns. Without a standardized DI approach, these critical integration points risk inconsistent initialization, difficult testing, and tight coupling to Android framework components. + +## Decision + +1. MUST: ViewModels handling Android Intent-based public API interactions MUST use HiltViewModel annotation for dependency injection + +## Policy Block + +- MUST ViewModels handling Android Intent-based public API interactions MUST use HiltViewModel annotation for dependency injection + +In scope: +- Android ViewModels handling credential provider APIs +- ViewModels processing authentication callback Intents +- ViewModels coordinating autofill service interactions +- Any ViewModel serving as boundary between Android system services and application logic + +Out of scope: +- Internal ViewModels not exposed to Android system APIs +- Fragment or Activity ViewModels handling only UI state +- Repository or manager layer components +- Non-Android platform integrations + +Exceptions: +- EXC-001: Legacy ViewModels predating Hilt adoption that require gradual migration + +## Rationale + +- Evidence shows 100% consistency across three distinct public API boundary ViewModels (credential provider, auth callback, autofill), indicating an established architectural pattern with 91.70% confidence +- HiltViewModel annotation provides Android-aware dependency injection that respects ViewModel lifecycle and survives configuration changes, critical for Intent-based system integrations +- Sealed action types and data classes create type-safe contracts that prevent runtime errors at public API boundaries where external systems interact with application logic +- Injected repository and manager components enable testability by allowing mock implementations during unit testing of Intent processing logic + +## Consequences + +Positive: +- Consistent dependency injection pattern across all public API boundary ViewModels improves maintainability and reduces cognitive load +- HiltViewModel lifecycle management prevents memory leaks and ensures proper cleanup of resources during configuration changes +- Testability improves through constructor injection, enabling unit tests with mock repositories without Android framework dependencies +- Type-safe sealed action contracts prevent runtime errors from malformed Intent data at system integration boundaries + +Negative: +- Introduces Hilt framework dependency for all public API ViewModels, increasing build complexity and annotation processing time +- Developers must understand Hilt scoping and lifecycle rules to correctly implement ViewModels at public API boundaries +- Migration of existing ViewModels to HiltViewModel pattern requires refactoring and testing effort +- Sealed action types increase boilerplate code compared to direct Intent parameter passing + +## Alternatives + +- Use manual ViewModel factory pattern with direct constructor injection (rejected) + Rejected because: Manual factory pattern requires boilerplate for each ViewModel and does not integrate with Android lifecycle-aware components as seamlessly as Hilt + When valid: In projects without Hilt or when minimizing annotation processing overhead is critical +- Use Dagger without Hilt for ViewModel injection (rejected) + Rejected because: Dagger alone requires more boilerplate and manual component management compared to Hilt's Android-specific optimizations + When valid: In projects with existing Dagger infrastructure where Hilt migration cost is prohibitive +- Use service locator pattern for dependency resolution in ViewModels (rejected) + Rejected because: Service locator pattern hides dependencies, reduces testability, and creates runtime dependency resolution failures instead of compile-time errors + When valid: Never recommended for new code; only acceptable in legacy codebases during gradual migration + +## Risks + +- Hilt annotation processing failures could break builds for all public API ViewModels simultaneously + Mitigation: Maintain Hilt version compatibility matrix, use Gradle dependency locking, and implement CI build verification for annotation processing + Owner: Engineering team +- Developers unfamiliar with Hilt may incorrectly scope dependencies, causing memory leaks or premature disposal + Mitigation: Provide ViewModel dependency injection guidelines, code review checklist, and automated lint rules to detect incorrect scoping + Owner: Architecture team +- Sealed action types may grow complex as public API contracts evolve, reducing maintainability + Mitigation: Establish action type design guidelines limiting nesting depth, use composition over inheritance, and refactor when action hierarchies exceed three levels + Owner: Engineering team + +## Implementation Notes + +- Annotate all public API boundary ViewModels with @HiltViewModel and ensure constructor parameters are annotated with @Inject +- Define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic +- Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel +- Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l +- grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l +- find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l + +Accept when: +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters + +## Enforcement + +- Verified by: Code review checklist requiring HiltViewModel annotation for all public API boundary ViewModels +- Verified by: Custom lint rule detecting ViewModels with Intent parameters lacking @HiltViewModel annotation +- Verified by: CI pipeline verification step running grep commands to validate pattern compliance +- Violation handling: CI build fails if public API ViewModels lack @HiltViewModel annotation +- Violation handling: Code review blocks merge if sealed action types are not used for Intent-based contracts +- Violation handling: Architecture team notified of violations for pattern compliance tracking +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in ADR exceptions registry with approval date and review schedule +- Exception process: Re-evaluate exception quarterly to assess migration feasibility \ No newline at end of file diff --git a/docs/adr/470c2bc4-87ff-4400-a07b-fb279d52be45-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-implementations-extend-console.md b/docs/adr/470c2bc4-87ff-4400-a07b-fb279d52be45-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-implementations-extend-console.md new file mode 100644 index 00000000000..b81ffde447a --- /dev/null +++ b/docs/adr/470c2bc4-87ff-4400-a07b-fb279d52be45-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-implementations-extend-console.md @@ -0,0 +1,114 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Implementations Extend Console + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements an MCP (Model Context Protocol) server using @modelcontextprotocol/sdk/server/index.js and stdio.js for communication +- Error conditions arise from both tool execution failures and fatal server-level errors requiring distinct logging contexts +- The server manages multiple tools accessed via a find pattern (tools.find(t => t.name === name)) requiring tool-scoped error identification +- Console-based logging provides immediate visibility in stdio-based server environments without external logging infrastructure dependencies +- The realtime boundary pattern (new Server with capabilities) necessitates synchronous error reporting for operational visibility + +## Problem Statement + +MCP servers operating over stdio require immediate, context-aware error logging that distinguishes between tool-level failures and fatal server errors while maintaining compatibility with the stdio transport layer and enabling operators to diagnose issues without external logging infrastructure. + +## Decision + +1. MAY: Implementations MAY extend console.error logging with structured error objects for enhanced debugging + +## Policy Block + +- MAY Implementations MAY extend console.error logging with structured error objects for enhanced debugging + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within the server capabilities boundary +- Fatal error conditions that terminate server operation +- Stdio-based transport layer error reporting + +Out of scope: +- Application-level logging within tool implementations +- Structured logging to external aggregation systems +- Client-side error handling and logging +- Non-error informational or debug logging + +## Rationale + +- The evidence shows explicit console.error usage for both tool-scoped errors (with name interpolation) and fatal errors, establishing a consistent pattern for synchronous error visibility +- The stdio transport layer used by @modelcontextprotocol/sdk/server/stdio.js requires console-based logging as the primary mechanism for operator visibility without interfering with protocol messages +- The tools.find pattern for tool resolution creates a natural boundary for tool-scoped error context, enabling precise error attribution +- The realtime server boundary (new Server with capabilities) necessitates immediate error reporting to maintain operational visibility during concurrent tool execution + +## Consequences + +Positive: +- Immediate error visibility in stdio-based environments without external dependencies +- Clear distinction between tool-level and server-level failures through consistent prefixing +- Simplified debugging through tool name context in error messages +- Zero-latency error reporting suitable for fatal error scenarios + +Negative: +- Console-based logging lacks structured metadata for automated analysis or aggregation +- No built-in error correlation across multiple tool invocations or server instances +- Limited filtering and search capabilities compared to structured logging systems +- Potential stderr pollution in environments with high error rates + +## Alternatives + +- Adopt structured logging library (e.g., winston, pino) with JSON output (rejected) + Rejected because: Adds external dependency and complexity for stdio-based MCP servers where console.error provides sufficient immediate visibility; structured logging better suited for long-running services with aggregation infrastructure + When valid: When MCP server operates in containerized environment with log aggregation pipeline or requires correlation across distributed tool executions +- Implement custom error event emitter with pluggable handlers (rejected) + Rejected because: Introduces abstraction overhead and delayed error reporting incompatible with fatal error scenarios requiring immediate visibility before process termination + When valid: When multiple error handling strategies must coexist or when error handling requires asynchronous processing +- Use MCP protocol error responses exclusively without console logging (rejected) + Rejected because: Protocol-level error responses do not provide operator visibility for fatal server errors or debugging during development; console logging serves distinct operational monitoring purpose + When valid: When all error handling occurs at client level and server-side operational monitoring is handled through external process supervision + +## Risks + +- Console error output may interfere with MCP protocol messages on stderr if not properly separated by transport layer + Mitigation: Verify @modelcontextprotocol/sdk/server/stdio.js properly isolates protocol messages from stderr; implement integration tests validating protocol integrity with error logging + Owner: MCP server engineering team +- Lack of structured error metadata limits automated error analysis and alerting capabilities + Mitigation: Document error message formats for parsing; consider hybrid approach with optional structured logging for production deployments while maintaining console.error baseline + Owner: Observability team +- Tool name context in error messages depends on correct name parameter propagation through tool resolution + Mitigation: Implement validation ensuring tool name is captured before execution; add fallback error logging for tool resolution failures + Owner: MCP server engineering team + +## Implementation Notes + +- Wrap all tool execution in try-catch blocks that call console.error with 'Tool error ({name}):' prefix before propagating or handling errors +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) before process exit +- Ensure tool name is captured from tools.find(t => t.name === name) result before execution to guarantee availability in error context +- Consider adding error codes or categories as structured prefixes within console.error messages to enable basic parsing without full structured logging + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ + +Accept when: +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + +## Enforcement + +- Verified by: Code review checking for console.error usage in error handling paths +- Verified by: Integration tests validating error log output format and content +- Verified by: Grep-based verification commands in CI pipeline +- Violation handling: Code review rejection for error handling without console.error logging +- Violation handling: CI pipeline warnings for missing tool name context in error logs +- Violation handling: Post-incident review when operational errors lack sufficient logging context +- Exception process: Document rationale for alternative logging approach in code comments +- Exception process: Obtain approval from observability team for structured logging adoption +- Exception process: Update ADR with amendment describing exception scope and justification \ No newline at end of file diff --git a/docs/adr/475964a8-a030-497f-8ce6-0cd39a8f5f03-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-json-data-loading.md b/docs/adr/475964a8-a030-497f-8ce6-0cd39a8f5f03-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-json-data-loading.md new file mode 100644 index 00000000000..918bdd273f1 --- /dev/null +++ b/docs/adr/475964a8-a030-497f-8ce6-0cd39a8f5f03-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-json-data-loading.md @@ -0,0 +1,118 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Json Data Loading + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test specifications and automation scripts across the codebase demonstrate consistent patterns of importing core libraries (vitest, node:fs, node:path, argparse, json, sys, os) and performing data access operations using collection methods like find(), add(), and load(). +- The pattern emerges in three distinct contexts: TypeScript test files using vitest for parsing dumpsys output, Python scripts for GitHub PR labeling automation, and Python scripts for JSON validation, indicating a cross-language consistency in data access approaches. +- Data access patterns consistently involve in-memory collection operations (Set.add(), Array.find()) and file-based JSON loading (json.load(f)), suggesting a preference for simple, direct data manipulation over abstraction layers. +- The detection spans test frameworks (describe, it), standard library imports (node:fs, node:path, argparse, json, sys, os), and runtime libraries (vitest), indicating these are foundational dependencies for testing and automation workflows. + +## Problem Statement + +The codebase lacks explicit guidance on which core libraries and data access patterns should be used for test specifications and automation scripts, leading to potential inconsistency in how data is loaded, queried, and manipulated across different modules and languages. + +## Decision + +1. SHOULD: JSON data loading SHOULD use json.load(f) in Python and JSON.parse() in TypeScript/JavaScript with explicit file handle management. + +## Policy Block + +- SHOULD JSON data loading SHOULD use json.load(f) in Python and JSON.parse() in TypeScript/JavaScript with explicit file handle management. + +In scope: +- Test specification files (*.spec.ts, *.test.ts) +- Automation scripts in .github/scripts/ +- Validation and parsing utilities +- CI/CD pipeline scripts + +Out of scope: +- Production application code with complex query requirements +- Database access layers requiring ORM or query builders +- High-performance data processing pipelines +- Browser-based test runners (e.g., Playwright, Cypress) + +Exceptions: +- EXC-001: Performance profiling indicates native collection methods create bottlenecks in large dataset processing +- EXC-002: External API contracts require specific JSON schema validation libraries beyond standard json module capabilities + +## Rationale + +- The evidence shows consistent use of standard library modules across 3 files with 90.83% confidence, indicating an established pattern that minimizes external dependencies and reduces maintenance burden. +- Using native collection methods (find(), add()) and standard library JSON parsing provides predictable behavior, reduces bundle size, and eliminates version compatibility issues with third-party libraries. +- The pattern spans both TypeScript (vitest, node:fs, node:path) and Python (json, sys, os, argparse) contexts, demonstrating language-appropriate choices that align with ecosystem conventions. +- Direct data access patterns without abstraction layers are appropriate for the observed use cases (test parsing, label automation, JSON validation) where query complexity is low and transparency is valuable. + +## Consequences + +Positive: +- Reduced dependency footprint in test and automation scripts, minimizing security surface area and dependency update overhead +- Improved script portability and long-term maintainability by relying on stable standard library APIs rather than third-party package ecosystems +- Lower cognitive overhead for developers familiar with standard library APIs, reducing onboarding time for test and automation contributions +- Faster script execution and smaller bundle sizes due to elimination of unnecessary abstraction layers + +Negative: +- Limited query expressiveness for complex data access patterns, requiring manual predicate logic rather than declarative query syntax +- Potential code duplication if similar data access patterns are repeated across multiple scripts without shared utility functions +- Lack of type safety in Python json.load() operations without additional validation layers or schema enforcement +- Manual error handling required for file I/O and JSON parsing operations without framework-provided retry or validation mechanisms + +## Alternatives + +- Adopt lodash/underscore for collection operations and data manipulation in both TypeScript and Python scripts (rejected) + Rejected because: Evidence shows native methods (Array.find(), Set.add()) are sufficient for current use cases; adding lodash would increase bundle size and introduce unnecessary dependency without demonstrated performance or expressiveness benefits + When valid: Valid for scripts processing large datasets requiring complex transformations like groupBy, partition, or deep merging +- Use Pydantic or JSON Schema validators for structured JSON validation instead of raw json.load() (deferred) + Rejected because: Current validation scripts use simple duplicate detection and basic structure checks; schema validation libraries add complexity without clear evidence of validation requirements beyond basic parsing + When valid: Valid when external API contracts require strict schema enforcement or when validation error messages need to be user-facing +- Standardize on Jest instead of vitest for TypeScript test specifications (rejected) + Rejected because: Evidence explicitly shows vitest usage in test specifications; Jest would require migration effort and vitest provides faster execution with native ESM support + When valid: Valid for projects requiring Jest-specific ecosystem plugins or snapshot testing features not available in vitest + +## Risks + +- Scripts may grow complex enough that native collection methods become verbose and error-prone, leading to maintenance burden + Mitigation: Establish shared utility modules for common data access patterns; set complexity threshold (e.g., >3 nested loops) triggering refactor to query library + Owner: Engineering team +- Lack of schema validation in JSON loading may allow malformed data to propagate through automation pipelines, causing runtime failures + Mitigation: Add explicit validation checks after json.load() for critical fields; document expected JSON structure in script docstrings; consider schema validation for external data sources + Owner: DevOps and automation team +- Standard library file I/O patterns may not handle edge cases (encoding issues, large files, concurrent access) as robustly as specialized libraries + Mitigation: Document encoding assumptions (UTF-8) explicitly; add file size checks for large file handling; use file locking for concurrent access scenarios + Owner: Engineering team + +## Implementation Notes + +- Create shared utility modules for common patterns: parseJsonFile(), findInCollection(), addToSet() to reduce duplication while maintaining standard library usage +- Add ESLint/Pylint rules to flag imports of lodash, ramda, or other collection libraries in test and automation script directories +- Document standard library API patterns in developer guide with examples from existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) +- For new automation scripts, use existing scripts as templates to ensure consistency in import patterns and data access approaches + +## Continuation Context + + +Verify commands: +- grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l +- grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l +- grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l +- grep -r "\.find(\|.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +Accept when: +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts + +## Enforcement + +- Verified by: CI pipeline static analysis checking for prohibited third-party imports in test and automation script directories +- Verified by: Code review checklist item verifying standard library usage for new test specifications and automation scripts +- Verified by: Automated dependency audits flagging new dependencies in package.json or requirements.txt within scope directories +- Violation handling: CI build fails if prohibited imports (lodash, ramda, etc.) are detected in test or automation scripts +- Violation handling: Pull requests adding external dependencies to automation scripts require architecture review and explicit justification +- Violation handling: Existing violations are tracked in technical debt backlog with migration plan to standard library equivalents +- Exception process: Submit exception request to tech lead with performance benchmarks or capability gap analysis +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration criteria +- Exception process: Review exceptions quarterly to assess if standard library improvements or refactoring can eliminate the need \ No newline at end of file diff --git a/docs/adr/478e5fed-094b-4ef2-afc1-88f9aa6956a4-enforce-schema-based-input-validation-for-public-api-endpoints-input-validation-occur.md b/docs/adr/478e5fed-094b-4ef2-afc1-88f9aa6956a4-enforce-schema-based-input-validation-for-public-api-endpoints-input-validation-occur.md new file mode 100644 index 00000000000..95fb5c78ea3 --- /dev/null +++ b/docs/adr/478e5fed-094b-4ef2-afc1-88f9aa6956a4-enforce-schema-based-input-validation-for-public-api-endpoints-input-validation-occur.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Input Validation Occur + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. MUST: Input validation MUST occur at the API boundary before the input reaches core business logic or is passed to downstream services + +## Policy Block + +- MUST Input validation MUST occur at the API boundary before the input reaches core business logic or is passed to downstream services + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/48843ec7-e1ab-4e68-95a6-f2d29f81c835-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-server-implementations-use.md b/docs/adr/48843ec7-e1ab-4e68-95a6-f2d29f81c835-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-server-implementations-use.md new file mode 100644 index 00000000000..7e539cb78a0 --- /dev/null +++ b/docs/adr/48843ec7-e1ab-4e68-95a6-f2d29f81c835-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-server-implementations-use.md @@ -0,0 +1,114 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Server Implementations Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-mcp server implementation requires structured error reporting for tool execution failures and fatal errors +- The @modelcontextprotocol/sdk provides server infrastructure including server/index.js, server/stdio.js, and types.js modules for building MCP-compliant servers +- Console-based error logging is used for both tool-level errors (with tool name context) and fatal server errors +- The server operates in a real-time boundary context with tool discovery patterns using array find operations +- Error visibility is critical for debugging tool execution failures in the MCP server environment + +## Problem Statement + +MCP server implementations need consistent error logging that captures both tool-specific failures and fatal server errors while maintaining compatibility with the @modelcontextprotocol/sdk framework and stdio-based communication patterns. + +## Decision + +1. SHOULD: Server implementations SHOULD use the Server constructor with name, version, and capabilities configuration + +## Policy Block + +- SHOULD Server implementations SHOULD use the Server constructor with name, version, and capabilities configuration + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within MCP servers +- Fatal error reporting in server lifecycle +- stdio-based MCP server communication + +Out of scope: +- Client-side MCP implementations +- Structured logging frameworks (e.g., Winston, Bunyan) +- Application-level business logic logging +- Performance metrics or tracing + +## Rationale + +- The evidence shows consistent use of console.error for both tool-level and fatal errors, establishing a pattern for error visibility in MCP server contexts +- The @modelcontextprotocol/sdk provides the foundational server infrastructure, making it a core dependency for MCP server implementations +- Console-based logging aligns with stdio-based server communication patterns where structured logging frameworks might interfere with the protocol +- The pattern of including tool names in error messages provides essential context for debugging in a tool-discovery architecture + +## Consequences + +Positive: +- Simple, dependency-free error logging that works immediately without configuration +- Compatible with stdio-based MCP protocol communication without interference +- Clear error context through structured message formats including tool names +- Minimal overhead for error reporting in real-time server operations + +Negative: +- Console.error lacks structured logging capabilities (no log levels, filtering, or formatting) +- No built-in log aggregation or persistence mechanisms +- Limited observability compared to dedicated logging frameworks +- Difficult to implement log sampling or rate limiting for high-frequency errors + +## Alternatives + +- Use a structured logging framework like Winston or Pino (rejected) + Rejected because: Structured logging frameworks may interfere with stdio-based MCP protocol communication and add unnecessary dependencies for simple error reporting + When valid: When MCP servers require log aggregation, filtering, or integration with centralized logging systems +- Implement custom error handling without console output (rejected) + Rejected because: Silent error handling would eliminate visibility into tool failures and fatal errors, making debugging impossible + When valid: Never valid for server implementations requiring operational visibility +- Use process.stderr.write for direct stream writing (rejected) + Rejected because: Direct stream writing requires manual formatting and lacks the convenience of console.error while providing minimal benefit + When valid: When precise control over stderr buffering or formatting is required + +## Risks + +- Console.error output may interfere with MCP protocol messages on stdio if not properly separated + Mitigation: Ensure stderr is used for errors (console.error) while stdout is reserved for protocol messages + Owner: engineering team +- Lack of log levels makes it difficult to filter or prioritize errors in production + Mitigation: Use consistent message prefixes ('Tool error', 'Fatal error') to enable grep-based filtering + Owner: engineering team +- No log persistence means errors are lost if not captured by process supervisor + Mitigation: Deploy MCP servers with process managers that capture stderr (systemd, PM2, Docker logging) + Owner: operations team + +## Implementation Notes + +- Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities +- Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}' +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) +- Ensure the server uses stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr) + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +Accept when: +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure + +## Enforcement + +- Verified by: Code review checking for console.error usage patterns +- Verified by: Grep-based verification commands in CI pipeline +- Verified by: Runtime testing of error scenarios to verify stderr output +- Violation handling: Code review feedback requesting correction to standard error logging format +- Violation handling: CI pipeline warnings for missing or non-standard error logging +- Violation handling: Documentation updates to clarify error logging requirements +- Exception process: Request exception through architecture review for alternative logging approaches +- Exception process: Document rationale for deviation including technical constraints +- Exception process: Obtain approval from platform team before implementing alternative logging \ No newline at end of file diff --git a/docs/adr/48f13c3a-a7cc-4d35-9b74-a5b204d2451d-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-public-endpoints-tool.md b/docs/adr/48f13c3a-a7cc-4d35-9b74-a5b204d2451d-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-public-endpoints-tool.md new file mode 100644 index 00000000000..459816f8301 --- /dev/null +++ b/docs/adr/48f13c3a-a7cc-4d35-9b74-a5b204d2451d-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-public-endpoints-tool.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Public Endpoints Tool + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. MUST: All public API endpoints and tool handlers MUST validate input parameters using zod schemas with explicit type constraints (z.number(), z.boolean(), z.string()) before processing + +## Policy Block + +- MUST All public API endpoints and tool handlers MUST validate input parameters using zod schemas with explicit type constraints (z.number(), z.boolean(), z.string()) before processing + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/4a66eb0d-cd6e-4ff9-9141-68acdc062e52-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-tests-use-mocking.md b/docs/adr/4a66eb0d-cd6e-4ff9-9141-68acdc062e52-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-tests-use-mocking.md new file mode 100644 index 00000000000..b53ef87f1bb --- /dev/null +++ b/docs/adr/4a66eb0d-cd6e-4ff9-9141-68acdc062e52-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-tests-use-mocking.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Tests Use Mocking + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. MAY: Tests MAY use mocking and patching utilities provided by the respective framework ecosystem (unittest.mock for Python, vitest mocking for TypeScript) + +## Policy Block + +- MAY Tests MAY use mocking and patching utilities provided by the respective framework ecosystem (unittest.mock for Python, vitest mocking for TypeScript) + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/4aea4cc3-aecc-4def-a941-be94472e80e2-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-androidx.md b/docs/adr/4aea4cc3-aecc-4def-a941-be94472e80e2-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-androidx.md new file mode 100644 index 00000000000..3c3e6e2850c --- /dev/null +++ b/docs/adr/4aea4cc3-aecc-4def-a941-be94472e80e2-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-androidx.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Composables Use Androidx + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. SHOULD: Composables SHOULD use androidx.compose.foundation.Image for image rendering within the composition hierarchy + +## Policy Block + +- SHOULD Composables SHOULD use androidx.compose.foundation.Image for image rendering within the composition hierarchy + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/4c90fdd9-d9d1-4228-9ca7-c4e47c517fe1-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-columnscope.md b/docs/adr/4c90fdd9-d9d1-4228-9ca7-c4e47c517fe1-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-columnscope.md new file mode 100644 index 00000000000..8f799d8e4ae --- /dev/null +++ b/docs/adr/4c90fdd9-d9d1-4228-9ca7-c4e47c517fe1-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composables-use-columnscope.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Composables Use Columnscope + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. MAY: Composables MAY use ColumnScope and other scope-specific APIs for context-aware layout composition + +## Policy Block + +- MAY Composables MAY use ColumnScope and other scope-specific APIs for context-aware layout composition + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/50429da5-fe1f-4c10-8c86-b3226b013d16-standardize-set-based-label-management-for-external-client-boundaries-external-calls-add.md b/docs/adr/50429da5-fe1f-4c10-8c86-b3226b013d16-standardize-set-based-label-management-for-external-client-boundaries-external-calls-add.md new file mode 100644 index 00000000000..5e7be971b5d --- /dev/null +++ b/docs/adr/50429da5-fe1f-4c10-8c86-b3226b013d16-standardize-set-based-label-management-for-external-client-boundaries-external-calls-add.md @@ -0,0 +1,115 @@ +# Standardize Set-Based Label Management for External Client Boundaries: External Calls Add + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes GitHub pull request metadata to classify and label changes based on title and path patterns +- External client boundaries require dynamic label assignment based on pattern matching against configuration-driven rules +- The system uses set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls +- Configuration is loaded from JSON files and parsed using standard library modules (argparse, json, os, subprocess, sys) +- The pattern emerged in automation scripts that bridge external GitHub API interactions with internal classification logic + +## Problem Statement + +When managing labels for external client boundaries such as GitHub pull requests, the system must efficiently accumulate, deduplicate, and conditionally apply labels based on pattern matching without introducing race conditions or duplicate API calls. A consistent data access pattern is needed to handle label state transitions and batch operations. + +## Decision + +1. MUST: External API calls (gh_add_labels, gh_replace_labels) MUST be invoked only after all labels have been accumulated locally + +## Policy Block + +- MUST External API calls (gh_add_labels, gh_replace_labels) MUST be invoked only after all labels have been accumulated locally + +In scope: +- GitHub pull request labeling automation scripts +- External client boundary interactions requiring label management +- Configuration-driven pattern matching workflows +- Set-based label accumulation and deduplication logic + +Out of scope: +- Internal database label storage or persistence +- Real-time streaming label updates +- Label management for non-GitHub external systems +- Manual label assignment workflows + +## Rationale + +- Set-based operations provide O(1) deduplication and membership testing, reducing complexity in label accumulation logic +- Batching label operations before external API calls minimizes network overhead and API rate limit consumption +- Pattern-driven configuration enables declarative label rules without code changes, improving maintainability +- The evidence shows consistent use of .add() and 'in' operators across label management, indicating an established pattern + +## Consequences + +Positive: +- Automatic deduplication prevents duplicate labels from being applied to pull requests +- Reduced API calls through batching improves performance and reduces rate limit pressure +- Declarative JSON configuration enables non-developers to modify labeling rules +- Set-based operations provide clear, idiomatic Python code that is easy to test and maintain + +Negative: +- Set-based approach loses ordering information if label application order matters +- In-memory accumulation requires all labels to be determined before any can be applied +- JSON configuration parsing adds a dependency on file I/O and introduces potential parsing errors +- Pattern matching complexity grows linearly with the number of configured patterns + +## Alternatives + +- Apply labels immediately upon pattern match without accumulation (rejected) + Rejected because: Would result in multiple API calls per PR and potential race conditions with concurrent label operations + When valid: When label order must be preserved or when real-time feedback is required +- Use list-based accumulation with manual deduplication (rejected) + Rejected because: Introduces O(n) membership checks and requires explicit deduplication logic, increasing complexity + When valid: When label ordering must be preserved or when duplicate labels have semantic meaning +- Store label state in a database with transactional updates (deferred) + Rejected because: Adds infrastructure complexity and latency for a lightweight automation script + When valid: When label history tracking, auditing, or multi-step workflows are required + +## Risks + +- JSON configuration parsing errors could cause automation failures and unlabeled pull requests + Mitigation: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting + Owner: engineering team +- Pattern matching complexity may degrade performance as configuration grows + Mitigation: Profile pattern matching performance and consider caching compiled patterns or using more efficient matching algorithms + Owner: engineering team +- Set-based deduplication may hide configuration errors where duplicate patterns exist + Mitigation: Add configuration validation to detect and warn about overlapping or duplicate patterns + Owner: engineering team + +## Implementation Notes + +- Initialize label sets early in the workflow to ensure all conditional branches can add labels safely +- Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels +- Validate JSON configuration schema on load to catch malformed patterns before runtime +- Consider logging the final label set before API calls to aid debugging and auditing +- Implement unit tests that verify set operations produce expected deduplication behavior + +## Continuation Context + + +Verify commands: +- grep -r '\.add("app:' .github/scripts/ | wc -l +- grep -r 'labels.*=.*set()' .github/scripts/ | wc -l +- python3 -m py_compile .github/scripts/label-pr.py + +Accept when: +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + +## Enforcement + +- Verified by: Code review of pull request automation scripts +- Verified by: Static analysis to detect non-set-based label accumulation patterns +- Verified by: Integration tests that verify label deduplication behavior +- Violation handling: Code review feedback requesting refactoring to set-based approach +- Violation handling: CI pipeline warnings when list-based label accumulation is detected +- Violation handling: Documentation updates to clarify the standard pattern +- Exception process: Document the specific requirement that necessitates deviation (e.g., label ordering) +- Exception process: Obtain approval from the platform engineering team +- Exception process: Add inline comments explaining why the exception is necessary \ No newline at end of file diff --git a/docs/adr/537e96b2-a713-4732-bd41-e78399595757-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-integration-test-scripts.md b/docs/adr/537e96b2-a713-4732-bd41-e78399595757-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-integration-test-scripts.md new file mode 100644 index 00000000000..52d3244338d --- /dev/null +++ b/docs/adr/537e96b2-a713-4732-bd41-e78399595757-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-integration-test-scripts.md @@ -0,0 +1,114 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Integration Test Scripts + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration scripts in .github/scripts/ interact with external APIs (JIRA, GitHub) where response structures may vary or contain optional fields +- Python's dictionary .get() method provides safe access to potentially missing keys without raising KeyError exceptions +- Two automation scripts (jira_release_notes.py, label-pr.py) demonstrate consistent use of .get() for accessing nested JSON response fields +- The pattern appears in CI/CD automation context where script failures would block workflows and require defensive programming + +## Problem Statement + +Integration scripts that parse external API responses need a consistent approach to handle optional or missing fields without causing runtime exceptions that would fail CI/CD workflows. Direct dictionary key access raises KeyError for missing keys, requiring explicit exception handling or key existence checks throughout the codebase. + +## Decision + +1. MUST: Integration test scripts MUST use the .get() method when accessing dictionary keys from external API responses + +## Policy Block + +- MUST Integration test scripts MUST use the .get() method when accessing dictionary keys from external API responses + +In scope: +- Python scripts in .github/scripts/ that parse JSON responses from external APIs +- Integration test utilities that process configuration files with optional fields +- Automation scripts that interact with GitHub API, JIRA API, or similar external services + +Out of scope: +- Internal data structures where key presence is guaranteed by construction +- Type-checked code using TypedDict or dataclasses where missing keys indicate programming errors +- Performance-critical paths where exception handling overhead is measured and acceptable + +Exceptions: +- EXC-001: API contract explicitly guarantees field presence and KeyError is preferred for contract violations + +## Rationale + +- The evidence shows consistent use of .get() across two independent scripts (jira_release_notes.py, label-pr.py) when accessing fields from external API responses, indicating an established pattern +- Using .get() prevents KeyError exceptions in CI/CD automation where script failures would block workflows and require manual intervention +- The pattern appears specifically in integration contexts (testing.integration facet) where external system responses are unpredictable +- Python's .get() method provides a concise, readable alternative to try-except blocks or explicit key existence checks + +## Consequences + +Positive: +- Reduced runtime exceptions in CI/CD workflows from missing or optional API response fields +- More resilient integration scripts that gracefully handle API schema variations +- Cleaner code without verbose try-except blocks or 'key in dict' checks +- Easier debugging with explicit default values visible at access points + +Negative: +- Silent failures possible if default values mask actual API errors or schema changes +- Potential confusion between missing keys (None) and explicit null values without additional checks +- May hide API contract violations that should be caught and reported +- Slightly less explicit than try-except blocks for documenting expected vs. exceptional cases + +## Alternatives + +- Use try-except blocks with KeyError handling for all dictionary access (rejected) + Rejected because: More verbose and reduces code readability; evidence shows .get() is preferred pattern in existing scripts + When valid: When explicit exception handling logic is needed or when distinguishing KeyError from other exceptions is important +- Use 'key in dict' checks before accessing each field (rejected) + Rejected because: Requires two dictionary lookups and increases code verbosity; .get() is more idiomatic Python + When valid: When the presence check itself needs to trigger different logic paths beyond default values +- Parse responses into typed dataclasses with validation (deferred) + Rejected because: Would require additional dependencies (pydantic, attrs) and refactoring; may be considered for future enhancement + When valid: For complex response schemas where full validation and type safety are required + +## Risks + +- API schema changes may go undetected if missing fields are silently handled with defaults + Mitigation: Log warnings when expected fields are missing; implement schema validation tests for critical API endpoints + Owner: Engineering team +- Inconsistent default value choices across scripts may lead to unexpected behavior + Mitigation: Document standard default values for common field types; review default choices in code review + Owner: Engineering team +- Overuse of .get() may mask programming errors in internal data structures + Mitigation: Limit .get() usage to external API boundaries as defined in policy scope; use direct access for internal structures + Owner: Engineering team + +## Implementation Notes + +- When accessing nested fields, use .get() with empty dict default for intermediate keys: response.get('fields', {}).get('field_name') +- Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling +- Add comments documenting why a field might be missing when using .get() for non-obvious cases +- Consider logging at debug level when .get() returns a default value to aid troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r '\.get(' .github/scripts/*.py | wc -l +- grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l +- python -m py_compile .github/scripts/*.py + +Accept when: +- Integration scripts in .github/scripts/ use .get() for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields + +## Enforcement + +- Verified by: Code review for new integration scripts +- Verified by: Grep-based verification in CI to detect bracket notation in API response handling +- Verified by: Runtime monitoring of CI/CD workflow failures +- Violation handling: Code review feedback requesting .get() usage for external API access +- Violation handling: CI workflow failures due to KeyError trigger review of dictionary access patterns +- Violation handling: Documentation updates if legitimate exceptions are identified +- Exception process: Document API contract guarantee in code comments +- Exception process: Obtain code review approval with explicit justification +- Exception process: Add to exception registry with EXC-001 reference \ No newline at end of file diff --git a/docs/adr/53b25493-fa5e-4734-bb63-dbe38cf09832-standardize-set-based-label-management-for-external-client-boundaries-application-specific-labels.md b/docs/adr/53b25493-fa5e-4734-bb63-dbe38cf09832-standardize-set-based-label-management-for-external-client-boundaries-application-specific-labels.md new file mode 100644 index 00000000000..70671a97792 --- /dev/null +++ b/docs/adr/53b25493-fa5e-4734-bb63-dbe38cf09832-standardize-set-based-label-management-for-external-client-boundaries-application-specific-labels.md @@ -0,0 +1,115 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Application Specific Labels + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes GitHub pull request metadata to classify and label changes based on title and path patterns +- External client boundaries require dynamic label assignment based on pattern matching against configuration-driven rules +- The system uses set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls +- Configuration is loaded from JSON files and parsed using standard library modules (argparse, json, os, subprocess, sys) +- The pattern emerged in automation scripts that bridge external GitHub API interactions with internal classification logic + +## Problem Statement + +When managing labels for external client boundaries such as GitHub pull requests, the system must efficiently accumulate, deduplicate, and conditionally apply labels based on pattern matching without introducing race conditions or duplicate API calls. A consistent data access pattern is needed to handle label state transitions and batch operations. + +## Decision + +1. MAY: Application-specific labels (e.g., app:password-manager, app:authenticator) MAY be added conditionally based on path patterns + +## Policy Block + +- MAY Application-specific labels (e.g., app:password-manager, app:authenticator) MAY be added conditionally based on path patterns + +In scope: +- GitHub pull request labeling automation scripts +- External client boundary interactions requiring label management +- Configuration-driven pattern matching workflows +- Set-based label accumulation and deduplication logic + +Out of scope: +- Internal database label storage or persistence +- Real-time streaming label updates +- Label management for non-GitHub external systems +- Manual label assignment workflows + +## Rationale + +- Set-based operations provide O(1) deduplication and membership testing, reducing complexity in label accumulation logic +- Batching label operations before external API calls minimizes network overhead and API rate limit consumption +- Pattern-driven configuration enables declarative label rules without code changes, improving maintainability +- The evidence shows consistent use of .add() and 'in' operators across label management, indicating an established pattern + +## Consequences + +Positive: +- Automatic deduplication prevents duplicate labels from being applied to pull requests +- Reduced API calls through batching improves performance and reduces rate limit pressure +- Declarative JSON configuration enables non-developers to modify labeling rules +- Set-based operations provide clear, idiomatic Python code that is easy to test and maintain + +Negative: +- Set-based approach loses ordering information if label application order matters +- In-memory accumulation requires all labels to be determined before any can be applied +- JSON configuration parsing adds a dependency on file I/O and introduces potential parsing errors +- Pattern matching complexity grows linearly with the number of configured patterns + +## Alternatives + +- Apply labels immediately upon pattern match without accumulation (rejected) + Rejected because: Would result in multiple API calls per PR and potential race conditions with concurrent label operations + When valid: When label order must be preserved or when real-time feedback is required +- Use list-based accumulation with manual deduplication (rejected) + Rejected because: Introduces O(n) membership checks and requires explicit deduplication logic, increasing complexity + When valid: When label ordering must be preserved or when duplicate labels have semantic meaning +- Store label state in a database with transactional updates (deferred) + Rejected because: Adds infrastructure complexity and latency for a lightweight automation script + When valid: When label history tracking, auditing, or multi-step workflows are required + +## Risks + +- JSON configuration parsing errors could cause automation failures and unlabeled pull requests + Mitigation: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting + Owner: engineering team +- Pattern matching complexity may degrade performance as configuration grows + Mitigation: Profile pattern matching performance and consider caching compiled patterns or using more efficient matching algorithms + Owner: engineering team +- Set-based deduplication may hide configuration errors where duplicate patterns exist + Mitigation: Add configuration validation to detect and warn about overlapping or duplicate patterns + Owner: engineering team + +## Implementation Notes + +- Initialize label sets early in the workflow to ensure all conditional branches can add labels safely +- Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels +- Validate JSON configuration schema on load to catch malformed patterns before runtime +- Consider logging the final label set before API calls to aid debugging and auditing +- Implement unit tests that verify set operations produce expected deduplication behavior + +## Continuation Context + + +Verify commands: +- grep -r '\.add("app:' .github/scripts/ | wc -l +- grep -r 'labels.*=.*set()' .github/scripts/ | wc -l +- python3 -m py_compile .github/scripts/label-pr.py + +Accept when: +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + +## Enforcement + +- Verified by: Code review of pull request automation scripts +- Verified by: Static analysis to detect non-set-based label accumulation patterns +- Verified by: Integration tests that verify label deduplication behavior +- Violation handling: Code review feedback requesting refactoring to set-based approach +- Violation handling: CI pipeline warnings when list-based label accumulation is detected +- Violation handling: Documentation updates to clarify the standard pattern +- Exception process: Document the specific requirement that necessitates deviation (e.g., label ordering) +- Exception process: Obtain approval from the platform engineering team +- Exception process: Add inline comments explaining why the exception is necessary \ No newline at end of file diff --git a/docs/adr/54a455ad-a22f-44a9-89e7-ec0b36cddbae-adopt-model-context-protocol-sdk-for-android-device-integration-tool-errors-logged.md b/docs/adr/54a455ad-a22f-44a9-89e7-ec0b36cddbae-adopt-model-context-protocol-sdk-for-android-device-integration-tool-errors-logged.md new file mode 100644 index 00000000000..20ab11b93df --- /dev/null +++ b/docs/adr/54a455ad-a22f-44a9-89e7-ec0b36cddbae-adopt-model-context-protocol-sdk-for-android-device-integration-tool-errors-logged.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Tool Errors Logged + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. MUST: Tool errors MUST be logged using console.error with tool name and error message context + +## Policy Block + +- MUST Tool errors MUST be logged using console.error with tool name and error message context + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/567e6deb-4b37-4322-83a0-0d882acc8bb1-enforce-schema-based-input-validation-for-public-api-endpoints-optional-parameters-declare.md b/docs/adr/567e6deb-4b37-4322-83a0-0d882acc8bb1-enforce-schema-based-input-validation-for-public-api-endpoints-optional-parameters-declare.md new file mode 100644 index 00000000000..0d8b935003a --- /dev/null +++ b/docs/adr/567e6deb-4b37-4322-83a0-0d882acc8bb1-enforce-schema-based-input-validation-for-public-api-endpoints-optional-parameters-declare.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Optional Parameters Declare + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. SHOULD: Optional parameters SHOULD declare explicit default values in the schema definition rather than handling defaults in business logic + +## Policy Block + +- SHOULD Optional parameters SHOULD declare explicit default values in the schema definition rather than handling defaults in business logic + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/56b52c53-ab5b-4371-9e76-41f731828a0d-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-use-direct.md b/docs/adr/56b52c53-ab5b-4371-9e76-41f731828a0d-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-use-direct.md new file mode 100644 index 00000000000..2a7f5063781 --- /dev/null +++ b/docs/adr/56b52c53-ab5b-4371-9e76-41f731828a0d-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-use-direct.md @@ -0,0 +1,114 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Scripts Use Direct + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration scripts in .github/scripts/ interact with external APIs (JIRA, GitHub) where response structures may vary or contain optional fields +- Python's dictionary .get() method provides safe access to potentially missing keys without raising KeyError exceptions +- Two automation scripts (jira_release_notes.py, label-pr.py) demonstrate consistent use of .get() for accessing nested JSON response fields +- The pattern appears in CI/CD automation context where script failures would block workflows and require defensive programming + +## Problem Statement + +Integration scripts that parse external API responses need a consistent approach to handle optional or missing fields without causing runtime exceptions that would fail CI/CD workflows. Direct dictionary key access raises KeyError for missing keys, requiring explicit exception handling or key existence checks throughout the codebase. + +## Decision + +1. SHOULD: Scripts SHOULD use direct key access (bracket notation) only when the field is guaranteed to exist by API contract or when KeyError is the desired behavior + +## Policy Block + +- SHOULD Scripts SHOULD use direct key access (bracket notation) only when the field is guaranteed to exist by API contract or when KeyError is the desired behavior + +In scope: +- Python scripts in .github/scripts/ that parse JSON responses from external APIs +- Integration test utilities that process configuration files with optional fields +- Automation scripts that interact with GitHub API, JIRA API, or similar external services + +Out of scope: +- Internal data structures where key presence is guaranteed by construction +- Type-checked code using TypedDict or dataclasses where missing keys indicate programming errors +- Performance-critical paths where exception handling overhead is measured and acceptable + +Exceptions: +- EXC-001: API contract explicitly guarantees field presence and KeyError is preferred for contract violations + +## Rationale + +- The evidence shows consistent use of .get() across two independent scripts (jira_release_notes.py, label-pr.py) when accessing fields from external API responses, indicating an established pattern +- Using .get() prevents KeyError exceptions in CI/CD automation where script failures would block workflows and require manual intervention +- The pattern appears specifically in integration contexts (testing.integration facet) where external system responses are unpredictable +- Python's .get() method provides a concise, readable alternative to try-except blocks or explicit key existence checks + +## Consequences + +Positive: +- Reduced runtime exceptions in CI/CD workflows from missing or optional API response fields +- More resilient integration scripts that gracefully handle API schema variations +- Cleaner code without verbose try-except blocks or 'key in dict' checks +- Easier debugging with explicit default values visible at access points + +Negative: +- Silent failures possible if default values mask actual API errors or schema changes +- Potential confusion between missing keys (None) and explicit null values without additional checks +- May hide API contract violations that should be caught and reported +- Slightly less explicit than try-except blocks for documenting expected vs. exceptional cases + +## Alternatives + +- Use try-except blocks with KeyError handling for all dictionary access (rejected) + Rejected because: More verbose and reduces code readability; evidence shows .get() is preferred pattern in existing scripts + When valid: When explicit exception handling logic is needed or when distinguishing KeyError from other exceptions is important +- Use 'key in dict' checks before accessing each field (rejected) + Rejected because: Requires two dictionary lookups and increases code verbosity; .get() is more idiomatic Python + When valid: When the presence check itself needs to trigger different logic paths beyond default values +- Parse responses into typed dataclasses with validation (deferred) + Rejected because: Would require additional dependencies (pydantic, attrs) and refactoring; may be considered for future enhancement + When valid: For complex response schemas where full validation and type safety are required + +## Risks + +- API schema changes may go undetected if missing fields are silently handled with defaults + Mitigation: Log warnings when expected fields are missing; implement schema validation tests for critical API endpoints + Owner: Engineering team +- Inconsistent default value choices across scripts may lead to unexpected behavior + Mitigation: Document standard default values for common field types; review default choices in code review + Owner: Engineering team +- Overuse of .get() may mask programming errors in internal data structures + Mitigation: Limit .get() usage to external API boundaries as defined in policy scope; use direct access for internal structures + Owner: Engineering team + +## Implementation Notes + +- When accessing nested fields, use .get() with empty dict default for intermediate keys: response.get('fields', {}).get('field_name') +- Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling +- Add comments documenting why a field might be missing when using .get() for non-obvious cases +- Consider logging at debug level when .get() returns a default value to aid troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r '\.get(' .github/scripts/*.py | wc -l +- grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l +- python -m py_compile .github/scripts/*.py + +Accept when: +- Integration scripts in .github/scripts/ use .get() for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields + +## Enforcement + +- Verified by: Code review for new integration scripts +- Verified by: Grep-based verification in CI to detect bracket notation in API response handling +- Verified by: Runtime monitoring of CI/CD workflow failures +- Violation handling: Code review feedback requesting .get() usage for external API access +- Violation handling: CI workflow failures due to KeyError trigger review of dictionary access patterns +- Violation handling: Documentation updates if legitimate exceptions are identified +- Exception process: Document API contract guarantee in code comments +- Exception process: Obtain code review approval with explicit justification +- Exception process: Add to exception registry with EXC-001 reference \ No newline at end of file diff --git a/docs/adr/575c687d-732e-4964-99df-666d2a785e8c-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-separate.md b/docs/adr/575c687d-732e-4964-99df-666d2a785e8c-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-separate.md new file mode 100644 index 00000000000..d751078b4a7 --- /dev/null +++ b/docs/adr/575c687d-732e-4964-99df-666d2a785e8c-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-separate.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Screen Implementations Separate + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. SHOULD: Screen implementations SHOULD separate UI composition (Screen composables) from event handling logic (Handler composables) + +## Policy Block + +- SHOULD Screen implementations SHOULD separate UI composition (Screen composables) from event handling logic (Handler composables) + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/591073da-b16d-422c-a912-e14441d427d0-adopt-async-handler-pattern-for-tool-operations-handler-functions-use.md b/docs/adr/591073da-b16d-422c-a912-e14441d427d0-adopt-async-handler-pattern-for-tool-operations-handler-functions-use.md new file mode 100644 index 00000000000..506c157c292 --- /dev/null +++ b/docs/adr/591073da-b16d-422c-a912-e14441d427d0-adopt-async-handler-pattern-for-tool-operations-handler-functions-use.md @@ -0,0 +1,120 @@ +# Adopt Async Handler Pattern for Tool Operations: Handler Functions Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the android-device-server MCP service. + +## Context + +- The android-device-server MCP service implements multiple tool operations (capture, tap-at, find-element-pipeline) that interact with external Android Debug Bridge (adb) processes and file system operations +- Tool operations require coordination of asynchronous I/O including process execution, file reads/writes, and validation steps that cannot block the event loop +- Each tool exports a handler function that serves as the primary entry point for tool invocation, establishing a consistent interface pattern across the codebase +- The codebase uses Zod for input validation schemas and node:path/node:fs for file system operations, requiring async coordination between validation and execution phases + +## Problem Statement + +Tool operations in the android-device-server require a consistent concurrency model that coordinates asynchronous validation, external process execution, and file system operations without blocking the Node.js event loop, while maintaining a uniform interface pattern across all tool implementations. + +## Decision + +1. SHOULD: Handler functions SHOULD use descriptive names that reflect the tool operation (e.g., capture, tapAt, findElementWithObstruction) + +## Policy Block + +- SHOULD Handler functions SHOULD use descriptive names that reflect the tool operation (e.g., capture, tapAt, findElementWithObstruction) + +In scope: +- All tool implementations in the android-device-server/src/tools directory +- Handler functions that coordinate adb process execution +- Operations involving file system reads/writes via node:fs +- Tool entry points exported for MCP service consumption + +Out of scope: +- Utility functions that do not serve as tool entry points +- Synchronous helper functions for data transformation +- Type definitions and interface declarations +- Test harness and mock implementations + +Exceptions: +- EXC-001: Pure computational functions that perform synchronous transformations without I/O + +## Rationale + +- The evidence shows consistent use of async handler functions (capture, tapAt, findElementWithObstruction) across 3 tool implementations, indicating an established pattern for coordinating asynchronous operations +- All detected tools import adb utilities and validation modules, requiring async coordination between validation, process execution, and result handling +- The handler pattern provides a uniform interface for tool invocation while encapsulating the complexity of async I/O coordination with external processes and file systems +- Using async/await patterns prevents event loop blocking and enables proper error propagation in the Node.js runtime environment + +## Consequences + +Positive: +- Consistent interface pattern across all tool implementations improves code maintainability and developer onboarding +- Non-blocking async operations ensure the MCP service remains responsive during long-running adb operations +- Separation of validation and execution phases enables early input rejection before expensive I/O operations +- Async/await syntax provides clear error handling and control flow compared to callback-based patterns + +Negative: +- Async handler pattern adds complexity compared to synchronous implementations for simple operations +- Requires developers to understand Promise semantics and async/await error handling +- Potential for unhandled promise rejections if error handling is not properly implemented +- Debugging async call stacks can be more challenging than synchronous execution flows + +## Alternatives + +- Synchronous handler functions with blocking I/O operations (rejected) + Rejected because: Blocking I/O would freeze the Node.js event loop during adb process execution and file operations, making the service unresponsive to concurrent requests + When valid: Only appropriate for pure computational functions without I/O dependencies +- Callback-based asynchronous pattern using Node.js callback conventions (rejected) + Rejected because: Callback patterns lead to nested callback hell and more complex error handling compared to async/await syntax available in modern Node.js + When valid: Legacy codebases or when targeting very old Node.js versions without async/await support +- Event emitter pattern for tool operations (rejected) + Rejected because: Event emitters add unnecessary complexity for request-response tool operations that have clear start and end points + When valid: Appropriate for streaming operations or long-running processes with multiple intermediate events + +## Risks + +- Unhandled promise rejections in handler functions could crash the Node.js process or leave operations in inconsistent states + Mitigation: Implement comprehensive try-catch blocks in all async handlers and configure Node.js to log unhandled rejections. Add integration tests that verify error handling paths. + Owner: Engineering team +- Long-running adb operations could accumulate pending promises and exhaust memory if not properly managed + Mitigation: Implement timeouts for all adb operations and add monitoring for pending promise counts. Consider implementing operation queuing with concurrency limits. + Owner: Engineering team +- Inconsistent error handling patterns across handlers could lead to unpredictable failure modes + Mitigation: Establish standard error handling patterns and document them. Create shared error handling utilities that all handlers can use. + Owner: Engineering team + +## Implementation Notes + +- All new tool implementations should follow the pattern: export an async function that accepts validated parameters and returns a Promise of the operation result +- Use Zod schemas defined at module level for input validation, and validate before entering the async handler logic +- Import adb utilities and file system operations from their respective modules (../adb/adb.js, node:fs, node:path) and await their results +- Ensure all async handlers have proper error handling with try-catch blocks and meaningful error messages that include context about the failed operation + +## Continuation Context + + +Verify commands: +- grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + +## Enforcement + +- Verified by: Code review checklist requiring async handler pattern for new tools +- Verified by: ESLint rules detecting synchronous I/O operations in tool handlers +- Verified by: Integration tests verifying non-blocking behavior under concurrent load +- Violation handling: Code review rejection for synchronous I/O in handler functions +- Violation handling: CI pipeline failure on ESLint violations for blocking operations +- Violation handling: Automated comments on PRs identifying missing async/await patterns +- Exception process: Document exception rationale in ADR amendment or inline code comments +- Exception process: Obtain tech lead approval for synchronous operations in tool handlers +- Exception process: Add exception to ESLint configuration with justification comment \ No newline at end of file diff --git a/docs/adr/59455fca-b2b2-4ac4-b814-b47e9dc84402-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-fatal-server-errors.md b/docs/adr/59455fca-b2b2-4ac4-b814-b47e9dc84402-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-fatal-server-errors.md new file mode 100644 index 00000000000..ed2c62b16a4 --- /dev/null +++ b/docs/adr/59455fca-b2b2-4ac4-b814-b47e9dc84402-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-fatal-server-errors.md @@ -0,0 +1,114 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Fatal Server Errors + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-mcp server implementation requires structured error reporting for tool execution failures and fatal errors +- The @modelcontextprotocol/sdk provides server infrastructure including server/index.js, server/stdio.js, and types.js modules for building MCP-compliant servers +- Console-based error logging is used for both tool-level errors (with tool name context) and fatal server errors +- The server operates in a real-time boundary context with tool discovery patterns using array find operations +- Error visibility is critical for debugging tool execution failures in the MCP server environment + +## Problem Statement + +MCP server implementations need consistent error logging that captures both tool-specific failures and fatal server errors while maintaining compatibility with the @modelcontextprotocol/sdk framework and stdio-based communication patterns. + +## Decision + +1. MUST: Fatal server errors MUST be logged using console.error with the format 'Fatal error: {error}' + +## Policy Block + +- MUST Fatal server errors MUST be logged using console.error with the format 'Fatal error: {error}' + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within MCP servers +- Fatal error reporting in server lifecycle +- stdio-based MCP server communication + +Out of scope: +- Client-side MCP implementations +- Structured logging frameworks (e.g., Winston, Bunyan) +- Application-level business logic logging +- Performance metrics or tracing + +## Rationale + +- The evidence shows consistent use of console.error for both tool-level and fatal errors, establishing a pattern for error visibility in MCP server contexts +- The @modelcontextprotocol/sdk provides the foundational server infrastructure, making it a core dependency for MCP server implementations +- Console-based logging aligns with stdio-based server communication patterns where structured logging frameworks might interfere with the protocol +- The pattern of including tool names in error messages provides essential context for debugging in a tool-discovery architecture + +## Consequences + +Positive: +- Simple, dependency-free error logging that works immediately without configuration +- Compatible with stdio-based MCP protocol communication without interference +- Clear error context through structured message formats including tool names +- Minimal overhead for error reporting in real-time server operations + +Negative: +- Console.error lacks structured logging capabilities (no log levels, filtering, or formatting) +- No built-in log aggregation or persistence mechanisms +- Limited observability compared to dedicated logging frameworks +- Difficult to implement log sampling or rate limiting for high-frequency errors + +## Alternatives + +- Use a structured logging framework like Winston or Pino (rejected) + Rejected because: Structured logging frameworks may interfere with stdio-based MCP protocol communication and add unnecessary dependencies for simple error reporting + When valid: When MCP servers require log aggregation, filtering, or integration with centralized logging systems +- Implement custom error handling without console output (rejected) + Rejected because: Silent error handling would eliminate visibility into tool failures and fatal errors, making debugging impossible + When valid: Never valid for server implementations requiring operational visibility +- Use process.stderr.write for direct stream writing (rejected) + Rejected because: Direct stream writing requires manual formatting and lacks the convenience of console.error while providing minimal benefit + When valid: When precise control over stderr buffering or formatting is required + +## Risks + +- Console.error output may interfere with MCP protocol messages on stdio if not properly separated + Mitigation: Ensure stderr is used for errors (console.error) while stdout is reserved for protocol messages + Owner: engineering team +- Lack of log levels makes it difficult to filter or prioritize errors in production + Mitigation: Use consistent message prefixes ('Tool error', 'Fatal error') to enable grep-based filtering + Owner: engineering team +- No log persistence means errors are lost if not captured by process supervisor + Mitigation: Deploy MCP servers with process managers that capture stderr (systemd, PM2, Docker logging) + Owner: operations team + +## Implementation Notes + +- Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities +- Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}' +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) +- Ensure the server uses stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr) + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +Accept when: +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure + +## Enforcement + +- Verified by: Code review checking for console.error usage patterns +- Verified by: Grep-based verification commands in CI pipeline +- Verified by: Runtime testing of error scenarios to verify stderr output +- Violation handling: Code review feedback requesting correction to standard error logging format +- Violation handling: CI pipeline warnings for missing or non-standard error logging +- Violation handling: Documentation updates to clarify error logging requirements +- Exception process: Request exception through architecture review for alternative logging approaches +- Exception process: Document rationale for deviation including technical constraints +- Exception process: Obtain approval from platform team before implementing alternative logging \ No newline at end of file diff --git a/docs/adr/597c203b-68e5-47e1-b387-760021689b99-use-json-builder-dsl-for-test-assertion-construction-test-methods-verifying.md b/docs/adr/597c203b-68e5-47e1-b387-760021689b99-use-json-builder-dsl-for-test-assertion-construction-test-methods-verifying.md new file mode 100644 index 00000000000..ebafce9a29b --- /dev/null +++ b/docs/adr/597c203b-68e5-47e1-b387-760021689b99-use-json-builder-dsl-for-test-assertion-construction-test-methods-verifying.md @@ -0,0 +1,101 @@ +# Use JSON Builder DSL for Test Assertion Construction: Test Methods Verifying + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests require verification that domain objects correctly encode to JSON with specific structure and type discriminators +- The codebase uses kotlinx.serialization for JSON encoding/decoding with custom serializers for versioned state objects +- Test assertions need to compare expected JSON structure against actual serializer output without string-based comparison fragility +- The buildJsonObject DSL with put operations provides type-safe construction of expected JSON structures for assertion matching + +## Problem Statement + +Test assertions for JSON serialization require a reliable method to construct expected JSON structures that can be compared against actual serializer output. String-based JSON comparison is fragile and difficult to maintain, while manual JsonObject construction is verbose and error-prone. A standardized approach is needed to build expected JSON structures in tests that is both readable and type-safe. + +## Decision + +1. SHOULD: Test methods verifying serialization SHOULD use assertEquals to compare buildJsonObject output with json.encodeToJsonElement results + +## Policy Block + +- SHOULD Test methods verifying serialization SHOULD use assertEquals to compare buildJsonObject output with json.encodeToJsonElement results + +## Rationale + +- The pattern appears in 2 test files with 91.70% confidence, both using buildJsonObject with put operations for JSON assertion construction +- WrappedAccountCryptographicStateSerializerTest demonstrates the pattern for versioned state objects (V1, V2) with type discriminators +- VaultSdkPolicyExtensionsTest shows the pattern applied to SDK policy conversion testing with empty list and multi-item list scenarios +- The kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put functions provide the DSL foundation for this testing approach + +## Consequences + +Positive: +- Type-safe JSON construction in tests reduces runtime errors from malformed JSON strings +- DSL syntax improves test readability by making JSON structure explicit and self-documenting +- Refactoring serialization logic becomes safer as tests clearly express expected structure +- IDE support for DSL provides autocomplete and type checking during test development + +Negative: +- Developers must learn kotlinx.serialization DSL syntax in addition to standard assertion libraries +- Verbose buildJsonObject blocks may increase test code size compared to raw JSON strings +- Pattern creates coupling to kotlinx.serialization library for test infrastructure +- Complex nested JSON structures may become difficult to read despite DSL benefits + +## Alternatives + +- Use raw JSON strings with Json.parseToJsonElement for expected values (rejected) + Rejected because: String-based JSON is fragile, lacks type safety, and requires manual escaping of special characters + When valid: Acceptable for simple one-off tests where JSON structure is trivial and unlikely to change +- Construct JsonObject instances directly using JsonObject constructor (rejected) + Rejected because: Direct constructor usage is verbose and less readable than DSL syntax, reducing test maintainability + When valid: Valid when buildJsonObject DSL is unavailable or when programmatic construction is required +- Use snapshot testing to capture serialized JSON output (deferred) + Rejected because: Not rejected but deferred; snapshot testing complements rather than replaces structural assertions + When valid: Useful for regression testing of large JSON structures where exact structure verification is needed + +## Risks + +- DSL syntax changes in kotlinx.serialization updates could break existing tests + Mitigation: Pin kotlinx.serialization version and review release notes before upgrades; maintain test suite coverage + Owner: engineering team +- Overuse of buildJsonObject for simple assertions may reduce test clarity + Mitigation: Establish guidelines for when DSL is appropriate versus simpler assertion methods; code review enforcement + Owner: engineering team +- New team members unfamiliar with kotlinx.serialization DSL may write inconsistent tests + Mitigation: Document pattern in testing guidelines; provide examples in test templates; conduct code review training + Owner: engineering team + +## Implementation Notes + +- Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern +- Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order +- For versioned state objects, always verify the type discriminator field first in the buildJsonObject block +- Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests + +## Continuation Context + + +Verify commands: +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l +- grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' +- ./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' + +Accept when: +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output + +## Enforcement + +- Verified by: Code review checklist requiring buildJsonObject usage in serialization tests +- Verified by: Static analysis or linting rules detecting raw JSON strings in test assertions +- Verified by: CI pipeline test execution validating serialization test coverage +- Violation handling: Code review feedback requesting refactoring to buildJsonObject DSL +- Violation handling: Pull request comments with examples of correct pattern usage +- Violation handling: Test failures flagged for investigation if serialization assertions use non-standard approaches +- Exception process: Document rationale in test comments when alternative assertion method is necessary +- Exception process: Obtain approval from tech lead for exceptions in complex or legacy test scenarios +- Exception process: Track exceptions in testing guidelines document with justification and review date \ No newline at end of file diff --git a/docs/adr/59851339-3655-43a8-8e80-a25247c1f58d-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-logging-occur.md b/docs/adr/59851339-3655-43a8-8e80-a25247c1f58d-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-logging-occur.md new file mode 100644 index 00000000000..f67928276ae --- /dev/null +++ b/docs/adr/59851339-3655-43a8-8e80-a25247c1f58d-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-logging-occur.md @@ -0,0 +1,114 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Error Logging Occur + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements an MCP (Model Context Protocol) server using @modelcontextprotocol/sdk/server/index.js and stdio.js for communication +- Error conditions arise from both tool execution failures and fatal server-level errors requiring distinct logging contexts +- The server manages multiple tools accessed via a find pattern (tools.find(t => t.name === name)) requiring tool-scoped error identification +- Console-based logging provides immediate visibility in stdio-based server environments without external logging infrastructure dependencies +- The realtime boundary pattern (new Server with capabilities) necessitates synchronous error reporting for operational visibility + +## Problem Statement + +MCP servers operating over stdio require immediate, context-aware error logging that distinguishes between tool-level failures and fatal server errors while maintaining compatibility with the stdio transport layer and enabling operators to diagnose issues without external logging infrastructure. + +## Decision + +1. MUST: Error logging MUST occur synchronously to ensure visibility before process termination in fatal scenarios + +## Policy Block + +- MUST Error logging MUST occur synchronously to ensure visibility before process termination in fatal scenarios + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within the server capabilities boundary +- Fatal error conditions that terminate server operation +- Stdio-based transport layer error reporting + +Out of scope: +- Application-level logging within tool implementations +- Structured logging to external aggregation systems +- Client-side error handling and logging +- Non-error informational or debug logging + +## Rationale + +- The evidence shows explicit console.error usage for both tool-scoped errors (with name interpolation) and fatal errors, establishing a consistent pattern for synchronous error visibility +- The stdio transport layer used by @modelcontextprotocol/sdk/server/stdio.js requires console-based logging as the primary mechanism for operator visibility without interfering with protocol messages +- The tools.find pattern for tool resolution creates a natural boundary for tool-scoped error context, enabling precise error attribution +- The realtime server boundary (new Server with capabilities) necessitates immediate error reporting to maintain operational visibility during concurrent tool execution + +## Consequences + +Positive: +- Immediate error visibility in stdio-based environments without external dependencies +- Clear distinction between tool-level and server-level failures through consistent prefixing +- Simplified debugging through tool name context in error messages +- Zero-latency error reporting suitable for fatal error scenarios + +Negative: +- Console-based logging lacks structured metadata for automated analysis or aggregation +- No built-in error correlation across multiple tool invocations or server instances +- Limited filtering and search capabilities compared to structured logging systems +- Potential stderr pollution in environments with high error rates + +## Alternatives + +- Adopt structured logging library (e.g., winston, pino) with JSON output (rejected) + Rejected because: Adds external dependency and complexity for stdio-based MCP servers where console.error provides sufficient immediate visibility; structured logging better suited for long-running services with aggregation infrastructure + When valid: When MCP server operates in containerized environment with log aggregation pipeline or requires correlation across distributed tool executions +- Implement custom error event emitter with pluggable handlers (rejected) + Rejected because: Introduces abstraction overhead and delayed error reporting incompatible with fatal error scenarios requiring immediate visibility before process termination + When valid: When multiple error handling strategies must coexist or when error handling requires asynchronous processing +- Use MCP protocol error responses exclusively without console logging (rejected) + Rejected because: Protocol-level error responses do not provide operator visibility for fatal server errors or debugging during development; console logging serves distinct operational monitoring purpose + When valid: When all error handling occurs at client level and server-side operational monitoring is handled through external process supervision + +## Risks + +- Console error output may interfere with MCP protocol messages on stderr if not properly separated by transport layer + Mitigation: Verify @modelcontextprotocol/sdk/server/stdio.js properly isolates protocol messages from stderr; implement integration tests validating protocol integrity with error logging + Owner: MCP server engineering team +- Lack of structured error metadata limits automated error analysis and alerting capabilities + Mitigation: Document error message formats for parsing; consider hybrid approach with optional structured logging for production deployments while maintaining console.error baseline + Owner: Observability team +- Tool name context in error messages depends on correct name parameter propagation through tool resolution + Mitigation: Implement validation ensuring tool name is captured before execution; add fallback error logging for tool resolution failures + Owner: MCP server engineering team + +## Implementation Notes + +- Wrap all tool execution in try-catch blocks that call console.error with 'Tool error ({name}):' prefix before propagating or handling errors +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) before process exit +- Ensure tool name is captured from tools.find(t => t.name === name) result before execution to guarantee availability in error context +- Consider adding error codes or categories as structured prefixes within console.error messages to enable basic parsing without full structured logging + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ + +Accept when: +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + +## Enforcement + +- Verified by: Code review checking for console.error usage in error handling paths +- Verified by: Integration tests validating error log output format and content +- Verified by: Grep-based verification commands in CI pipeline +- Violation handling: Code review rejection for error handling without console.error logging +- Violation handling: CI pipeline warnings for missing tool name context in error logs +- Violation handling: Post-incident review when operational errors lack sufficient logging context +- Exception process: Document rationale for alternative logging approach in code comments +- Exception process: Obtain approval from observability team for structured logging adoption +- Exception process: Update ADR with amendment describing exception scope and justification \ No newline at end of file diff --git a/docs/adr/5b55513f-9bc8-4c6d-a31b-ccff626de6ca-adopt-zod-schema-validation-for-tool-input-parameters-tool-handlers-that.md b/docs/adr/5b55513f-9bc8-4c6d-a31b-ccff626de6ca-adopt-zod-schema-validation-for-tool-input-parameters-tool-handlers-that.md new file mode 100644 index 00000000000..9f2d626ce98 --- /dev/null +++ b/docs/adr/5b55513f-9bc8-4c6d-a31b-ccff626de6ca-adopt-zod-schema-validation-for-tool-input-parameters-tool-handlers-that.md @@ -0,0 +1,116 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Tool Handlers That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the Android Device Server MCP that accept external input parameters. + +## Context + +- The Android Device Server MCP exposes tool handlers that accept external input from clients, requiring validation to prevent invalid operations and runtime errors +- Tool parameters include coordinates, timing values, and boolean flags that must conform to specific constraints (non-negative integers, minimum values, type safety) +- The codebase imports 'zod' as a core dependency and '../utils/validation.js' across multiple tool implementations, indicating a standardized validation approach +- Two tool handlers (capture.ts and tap-at.ts) demonstrate consistent schema definition patterns using z.object() with typed field validators + +## Problem Statement + +Tool handlers in the Android Device Server MCP must validate external input parameters to ensure type safety, enforce domain constraints (e.g., non-negative coordinates, valid timing ranges), and prevent invalid ADB commands from being executed, but without a standardized validation approach, each tool would implement ad-hoc validation logic leading to inconsistency and maintenance burden. + +## Decision + +1. MUST: All tool handlers that accept external input parameters MUST define a Zod schema using z.object() to validate input structure and types + +## Policy Block + +- MUST All tool handlers that accept external input parameters MUST define a Zod schema using z.object() to validate input structure and types + +In scope: +- All tool handler implementations in src/tools/ that accept external parameters +- Input validation for ADB command parameters (coordinates, timing, flags) +- Public API contracts exposed through MCP tool interfaces + +Out of scope: +- Internal utility functions that do not accept external input +- ADB command output parsing and response formatting +- Device discovery and connection management logic + +## Rationale + +- The evidence shows consistent use of Zod schemas across capture.ts and tap-at.ts with identical import patterns ('zod', '../utils/validation.js'), indicating an established validation standard +- Schema definitions enforce domain-specific constraints (non-negative coordinates, minimum timing values) that prevent invalid ADB commands and improve system reliability +- Centralized validation through Zod provides type inference, runtime validation, and clear error messages, reducing boilerplate and improving developer experience +- The pattern appears in the security.input_validation facet with 91.20% confidence across 2 files, demonstrating measurable adoption + +## Consequences + +Positive: +- Type-safe input validation with automatic TypeScript type inference from schemas +- Consistent validation error messages and handling across all tool implementations +- Reduced boilerplate code compared to manual parameter checking and validation +- Clear API contracts that are self-documenting through schema definitions + +Negative: +- Additional runtime overhead for schema validation on every tool invocation +- Dependency on the Zod library increases bundle size and introduces external maintenance risk +- Developers must learn Zod API and schema composition patterns +- Schema definitions add verbosity to tool handler implementations + +## Alternatives + +- Manual parameter validation using TypeScript type guards and conditional checks (rejected) + Rejected because: Leads to inconsistent validation logic, verbose boilerplate, and no runtime type safety guarantees + When valid: For simple internal functions with minimal validation requirements +- Use JSON Schema with ajv validator for runtime validation (rejected) + Rejected because: Requires separate type definitions and schema definitions, losing TypeScript type inference benefits + When valid: When interoperating with systems that already use JSON Schema standards +- Use io-ts for functional programming style validation (rejected) + Rejected because: Steeper learning curve and more verbose syntax compared to Zod's developer-friendly API + When valid: In codebases with strong functional programming conventions using fp-ts + +## Risks + +- Zod library vulnerabilities or breaking changes in future versions could impact all tool handlers + Mitigation: Pin Zod version in package.json, monitor security advisories, and maintain comprehensive test coverage for validation logic + Owner: engineering team +- Complex nested schemas may introduce performance bottlenecks for high-frequency tool invocations + Mitigation: Profile validation performance, cache parsed schemas, and consider lazy validation for optional deep structures + Owner: engineering team +- Inconsistent schema patterns across tools if validation utilities are not properly documented + Mitigation: Document standard validation patterns in ../utils/validation.js, provide schema templates, and enforce through code review + Owner: engineering team + +## Implementation Notes + +- Import Zod and validation utilities at the top of each tool handler: import { z } from 'zod' and import validation utilities from '../utils/validation.js' +- Define the input schema as a const using z.object() with appropriate field validators before the handler function +- Use .int().nonnegative() for coordinate parameters, .min(0) for timing parameters, and .optional().default() for optional flags +- Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages +- Export the inferred TypeScript type using z.infer for use in function signatures and documentation + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "../utils/validation" .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool handlers in src/tools/ that accept external parameters import 'zod' and define validation schemas +- Grep commands show consistent usage of z.object() schema definitions across tool implementations +- Validation utility imports from '../utils/validation.js' are present in all relevant tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for new tool handlers +- Verified by: Automated grep-based checks in CI pipeline verifying presence of validation imports +- Verified by: TypeScript compilation ensuring type safety through schema inference +- Violation handling: Pull requests adding tool handlers without Zod validation are rejected during code review +- Violation handling: CI pipeline fails if tool files lack required validation imports +- Violation handling: Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation +- Exception process: Exceptions require written justification documenting why Zod validation is inappropriate for the specific use case +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in code comments with reference to approval decision \ No newline at end of file diff --git a/docs/adr/5bf424b3-89eb-4096-8559-2239b4337494-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-provide-appropriate.md b/docs/adr/5bf424b3-89eb-4096-8559-2239b4337494-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-provide-appropriate.md new file mode 100644 index 00000000000..a2d76e315cf --- /dev/null +++ b/docs/adr/5bf424b3-89eb-4096-8559-2239b4337494-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-scripts-provide-appropriate.md @@ -0,0 +1,114 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Scripts Provide Appropriate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration scripts in .github/scripts/ interact with external APIs (JIRA, GitHub) where response structures may vary or contain optional fields +- Python's dictionary .get() method provides safe access to potentially missing keys without raising KeyError exceptions +- Two automation scripts (jira_release_notes.py, label-pr.py) demonstrate consistent use of .get() for accessing nested JSON response fields +- The pattern appears in CI/CD automation context where script failures would block workflows and require defensive programming + +## Problem Statement + +Integration scripts that parse external API responses need a consistent approach to handle optional or missing fields without causing runtime exceptions that would fail CI/CD workflows. Direct dictionary key access raises KeyError for missing keys, requiring explicit exception handling or key existence checks throughout the codebase. + +## Decision + +1. MUST: Scripts MUST provide appropriate default values to .get() when a missing field should result in a specific fallback behavior + +## Policy Block + +- MUST Scripts MUST provide appropriate default values to .get() when a missing field should result in a specific fallback behavior + +In scope: +- Python scripts in .github/scripts/ that parse JSON responses from external APIs +- Integration test utilities that process configuration files with optional fields +- Automation scripts that interact with GitHub API, JIRA API, or similar external services + +Out of scope: +- Internal data structures where key presence is guaranteed by construction +- Type-checked code using TypedDict or dataclasses where missing keys indicate programming errors +- Performance-critical paths where exception handling overhead is measured and acceptable + +Exceptions: +- EXC-001: API contract explicitly guarantees field presence and KeyError is preferred for contract violations + +## Rationale + +- The evidence shows consistent use of .get() across two independent scripts (jira_release_notes.py, label-pr.py) when accessing fields from external API responses, indicating an established pattern +- Using .get() prevents KeyError exceptions in CI/CD automation where script failures would block workflows and require manual intervention +- The pattern appears specifically in integration contexts (testing.integration facet) where external system responses are unpredictable +- Python's .get() method provides a concise, readable alternative to try-except blocks or explicit key existence checks + +## Consequences + +Positive: +- Reduced runtime exceptions in CI/CD workflows from missing or optional API response fields +- More resilient integration scripts that gracefully handle API schema variations +- Cleaner code without verbose try-except blocks or 'key in dict' checks +- Easier debugging with explicit default values visible at access points + +Negative: +- Silent failures possible if default values mask actual API errors or schema changes +- Potential confusion between missing keys (None) and explicit null values without additional checks +- May hide API contract violations that should be caught and reported +- Slightly less explicit than try-except blocks for documenting expected vs. exceptional cases + +## Alternatives + +- Use try-except blocks with KeyError handling for all dictionary access (rejected) + Rejected because: More verbose and reduces code readability; evidence shows .get() is preferred pattern in existing scripts + When valid: When explicit exception handling logic is needed or when distinguishing KeyError from other exceptions is important +- Use 'key in dict' checks before accessing each field (rejected) + Rejected because: Requires two dictionary lookups and increases code verbosity; .get() is more idiomatic Python + When valid: When the presence check itself needs to trigger different logic paths beyond default values +- Parse responses into typed dataclasses with validation (deferred) + Rejected because: Would require additional dependencies (pydantic, attrs) and refactoring; may be considered for future enhancement + When valid: For complex response schemas where full validation and type safety are required + +## Risks + +- API schema changes may go undetected if missing fields are silently handled with defaults + Mitigation: Log warnings when expected fields are missing; implement schema validation tests for critical API endpoints + Owner: Engineering team +- Inconsistent default value choices across scripts may lead to unexpected behavior + Mitigation: Document standard default values for common field types; review default choices in code review + Owner: Engineering team +- Overuse of .get() may mask programming errors in internal data structures + Mitigation: Limit .get() usage to external API boundaries as defined in policy scope; use direct access for internal structures + Owner: Engineering team + +## Implementation Notes + +- When accessing nested fields, use .get() with empty dict default for intermediate keys: response.get('fields', {}).get('field_name') +- Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling +- Add comments documenting why a field might be missing when using .get() for non-obvious cases +- Consider logging at debug level when .get() returns a default value to aid troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r '\.get(' .github/scripts/*.py | wc -l +- grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l +- python -m py_compile .github/scripts/*.py + +Accept when: +- Integration scripts in .github/scripts/ use .get() for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields + +## Enforcement + +- Verified by: Code review for new integration scripts +- Verified by: Grep-based verification in CI to detect bracket notation in API response handling +- Verified by: Runtime monitoring of CI/CD workflow failures +- Violation handling: Code review feedback requesting .get() usage for external API access +- Violation handling: CI workflow failures due to KeyError trigger review of dictionary access patterns +- Violation handling: Documentation updates if legitimate exceptions are identified +- Exception process: Document API contract guarantee in code comments +- Exception process: Obtain code review approval with explicit justification +- Exception process: Add to exception registry with EXC-001 reference \ No newline at end of file diff --git a/docs/adr/5dab80b0-9a3b-4743-8d55-84d6db3f8171-standardize-kotlinx-serialization-json-testing-with-type-discriminators-when-type-discriminators.md b/docs/adr/5dab80b0-9a3b-4743-8d55-84d6db3f8171-standardize-kotlinx-serialization-json-testing-with-type-discriminators-when-type-discriminators.md new file mode 100644 index 00000000000..5efe0b405e4 --- /dev/null +++ b/docs/adr/5dab80b0-9a3b-4743-8d55-84d6db3f8171-standardize-kotlinx-serialization-json-testing-with-type-discriminators-when-type-discriminators.md @@ -0,0 +1,116 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: When Type Discriminators + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests validate JSON encoding/decoding behavior at service boundaries where data crosses module or API boundaries +- The codebase uses kotlinx.serialization for JSON serialization with custom serializers for domain models like WrappedAccountCryptographicState +- Type discriminators (e.g., 'v1', 'v2') enable versioned serialization formats to support backward compatibility and schema evolution +- Tests use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings +- The pattern appears in cryptographic state serialization and policy view conversion, indicating cross-cutting serialization concerns + +## Problem Statement + +Service boundaries require reliable serialization contracts that can evolve over time without breaking existing clients. Without standardized testing of JSON serialization including type discriminators and property mappings, schema changes may introduce silent data corruption or deserialization failures at runtime. + +## Decision + +1. MUST: When using type discriminators for versioned schemas, tests MUST verify the discriminator field value for each version + +## Policy Block + +- MUST When using type discriminators for versioned schemas, tests MUST verify the discriminator field value for each version + +In scope: +- Custom kotlinx.serialization serializers for domain models +- Extension functions converting between domain models and SDK types +- JSON encoding/decoding at service and module boundaries +- Versioned serialization formats using type discriminators + +Out of scope: +- Internal data transformations that do not cross serialization boundaries +- Third-party library serializers without custom logic +- Binary serialization formats +- Database entity mappings + +## Rationale + +- The evidence shows consistent use of kotlinx.serialization.json.buildJsonObject and assertEquals patterns across serialization tests, indicating an established testing approach +- Type discriminators ('v1', 'v2') in WrappedAccountCryptographicState tests demonstrate versioning requirements at cryptographic state boundaries +- Tests for toSdkPolicyViews extension function show validation of conversion logic between network models and SDK policy views +- The pattern appears in both data layer (cryptographic state) and vault repository (policy conversion), suggesting cross-cutting serialization concerns requiring standardized testing + +## Consequences + +Positive: +- Serialization contract changes are caught at test time rather than runtime, preventing data corruption +- Type discriminator validation ensures versioned schemas maintain backward compatibility +- Standardized test structure improves maintainability and makes serialization behavior explicit +- Extension function tests verify boundary conversions handle edge cases like empty lists + +Negative: +- Additional test code increases maintenance burden when serialization formats change +- Exact JSON structure assertions are brittle and may require updates for cosmetic changes +- Test duplication across similar serializers may occur without shared test utilities +- Mock factory functions add indirection that may obscure actual test data + +## Alternatives + +- Use property-based testing to verify serialization round-trips without asserting exact JSON structure (rejected) + Rejected because: Does not validate exact JSON contract including field names and discriminator values required for external API compatibility + When valid: Internal serialization where only round-trip fidelity matters, not exact wire format +- Generate serialization tests automatically from schema definitions (deferred) + Rejected because: Requires additional tooling and schema-first development approach not currently in place + When valid: When adopting schema-first API design with OpenAPI or JSON Schema definitions +- Rely on integration tests to catch serialization issues (rejected) + Rejected because: Integration tests are slower, less isolated, and provide poor feedback for serialization contract violations + When valid: Never as sole verification; integration tests complement but do not replace unit-level serialization tests + +## Risks + +- Brittle tests that break on benign JSON formatting changes (e.g., property order) + Mitigation: Use JSON comparison that ignores property order; consider semantic equality checks for non-critical formatting + Owner: engineering team +- Test coverage gaps for deserialization paths and error handling + Mitigation: Extend testing standard to include deserialization tests and malformed input handling + Owner: engineering team +- Type discriminator values may conflict across different serializers + Mitigation: Establish discriminator naming conventions and maintain registry of used discriminator values + Owner: architecture team + +## Implementation Notes + +- Create test classes in src/test/kotlin mirroring the package structure of serializers under test +- Use @Test annotation and assertEquals with buildJsonObject for exact JSON structure validation +- For versioned schemas, create separate test methods for each version verifying the type discriminator field +- When testing extension functions like toSdkPolicyViews, include edge cases such as empty lists and multi-item collections +- Consider extracting mock factory functions (e.g., createMockPolicy) to shared test utilities for reuse across test classes + +## Continuation Context + + +Verify commands: +- grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l +- find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +Accept when: +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + +## Enforcement + +- Verified by: Code review checklist requiring serialization tests for new serializers +- Verified by: CI pipeline test coverage reporting for serialization packages +- Verified by: Static analysis detecting serializers without corresponding test classes +- Violation handling: Pull requests adding serializers without tests are blocked in code review +- Violation handling: Coverage reports flag untested serialization code for remediation +- Violation handling: Architecture review required for serializers lacking discriminator validation +- Exception process: Exceptions require architecture team approval with documented justification +- Exception process: Temporary exceptions must include remediation plan and timeline +- Exception process: Exception requests must demonstrate why alternative testing approach provides equivalent contract validation \ No newline at end of file diff --git a/docs/adr/600b7997-bad6-44c8-8d7c-7eaee2b25819-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-public-test-contracts.md b/docs/adr/600b7997-bad6-44c8-8d7c-7eaee2b25819-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-public-test-contracts.md new file mode 100644 index 00000000000..c434269de0f --- /dev/null +++ b/docs/adr/600b7997-bad6-44c8-8d7c-7eaee2b25819-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-public-test-contracts.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Public Test Contracts + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. MUST: Public test contracts MUST be expressed as methods prefixed with 'test_' that describe the behavior being validated + +## Policy Block + +- MUST Public test contracts MUST be expressed as methods prefixed with 'test_' that describe the behavior being validated + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/63609e18-cbc0-489d-8d3a-719e16b42c27-standardize-set-based-label-management-for-external-client-boundaries-label-accumulation-use.md b/docs/adr/63609e18-cbc0-489d-8d3a-719e16b42c27-standardize-set-based-label-management-for-external-client-boundaries-label-accumulation-use.md new file mode 100644 index 00000000000..9a9939d45e2 --- /dev/null +++ b/docs/adr/63609e18-cbc0-489d-8d3a-719e16b42c27-standardize-set-based-label-management-for-external-client-boundaries-label-accumulation-use.md @@ -0,0 +1,115 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Label Accumulation Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes GitHub pull request metadata to classify and label changes based on title and path patterns +- External client boundaries require dynamic label assignment based on pattern matching against configuration-driven rules +- The system uses set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls +- Configuration is loaded from JSON files and parsed using standard library modules (argparse, json, os, subprocess, sys) +- The pattern emerged in automation scripts that bridge external GitHub API interactions with internal classification logic + +## Problem Statement + +When managing labels for external client boundaries such as GitHub pull requests, the system must efficiently accumulate, deduplicate, and conditionally apply labels based on pattern matching without introducing race conditions or duplicate API calls. A consistent data access pattern is needed to handle label state transitions and batch operations. + +## Decision + +1. MUST: Label accumulation MUST use set-based data structures to ensure automatic deduplication + +## Policy Block + +- MUST Label accumulation MUST use set-based data structures to ensure automatic deduplication + +In scope: +- GitHub pull request labeling automation scripts +- External client boundary interactions requiring label management +- Configuration-driven pattern matching workflows +- Set-based label accumulation and deduplication logic + +Out of scope: +- Internal database label storage or persistence +- Real-time streaming label updates +- Label management for non-GitHub external systems +- Manual label assignment workflows + +## Rationale + +- Set-based operations provide O(1) deduplication and membership testing, reducing complexity in label accumulation logic +- Batching label operations before external API calls minimizes network overhead and API rate limit consumption +- Pattern-driven configuration enables declarative label rules without code changes, improving maintainability +- The evidence shows consistent use of .add() and 'in' operators across label management, indicating an established pattern + +## Consequences + +Positive: +- Automatic deduplication prevents duplicate labels from being applied to pull requests +- Reduced API calls through batching improves performance and reduces rate limit pressure +- Declarative JSON configuration enables non-developers to modify labeling rules +- Set-based operations provide clear, idiomatic Python code that is easy to test and maintain + +Negative: +- Set-based approach loses ordering information if label application order matters +- In-memory accumulation requires all labels to be determined before any can be applied +- JSON configuration parsing adds a dependency on file I/O and introduces potential parsing errors +- Pattern matching complexity grows linearly with the number of configured patterns + +## Alternatives + +- Apply labels immediately upon pattern match without accumulation (rejected) + Rejected because: Would result in multiple API calls per PR and potential race conditions with concurrent label operations + When valid: When label order must be preserved or when real-time feedback is required +- Use list-based accumulation with manual deduplication (rejected) + Rejected because: Introduces O(n) membership checks and requires explicit deduplication logic, increasing complexity + When valid: When label ordering must be preserved or when duplicate labels have semantic meaning +- Store label state in a database with transactional updates (deferred) + Rejected because: Adds infrastructure complexity and latency for a lightweight automation script + When valid: When label history tracking, auditing, or multi-step workflows are required + +## Risks + +- JSON configuration parsing errors could cause automation failures and unlabeled pull requests + Mitigation: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting + Owner: engineering team +- Pattern matching complexity may degrade performance as configuration grows + Mitigation: Profile pattern matching performance and consider caching compiled patterns or using more efficient matching algorithms + Owner: engineering team +- Set-based deduplication may hide configuration errors where duplicate patterns exist + Mitigation: Add configuration validation to detect and warn about overlapping or duplicate patterns + Owner: engineering team + +## Implementation Notes + +- Initialize label sets early in the workflow to ensure all conditional branches can add labels safely +- Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels +- Validate JSON configuration schema on load to catch malformed patterns before runtime +- Consider logging the final label set before API calls to aid debugging and auditing +- Implement unit tests that verify set operations produce expected deduplication behavior + +## Continuation Context + + +Verify commands: +- grep -r '\.add("app:' .github/scripts/ | wc -l +- grep -r 'labels.*=.*set()' .github/scripts/ | wc -l +- python3 -m py_compile .github/scripts/label-pr.py + +Accept when: +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + +## Enforcement + +- Verified by: Code review of pull request automation scripts +- Verified by: Static analysis to detect non-set-based label accumulation patterns +- Verified by: Integration tests that verify label deduplication behavior +- Violation handling: Code review feedback requesting refactoring to set-based approach +- Violation handling: CI pipeline warnings when list-based label accumulation is detected +- Violation handling: Documentation updates to clarify the standard pattern +- Exception process: Document the specific requirement that necessitates deviation (e.g., label ordering) +- Exception process: Obtain approval from the platform engineering team +- Exception process: Add inline comments explaining why the exception is necessary \ No newline at end of file diff --git a/docs/adr/65578697-b9b2-469e-b60a-75d8f7d82639-use-json-builder-dsl-for-test-assertion-construction-json-object-construction.md b/docs/adr/65578697-b9b2-469e-b60a-75d8f7d82639-use-json-builder-dsl-for-test-assertion-construction-json-object-construction.md new file mode 100644 index 00000000000..87be9955c5a --- /dev/null +++ b/docs/adr/65578697-b9b2-469e-b60a-75d8f7d82639-use-json-builder-dsl-for-test-assertion-construction-json-object-construction.md @@ -0,0 +1,101 @@ +# Use JSON Builder DSL for Test Assertion Construction: Json Object Construction + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests require verification that domain objects correctly encode to JSON with specific structure and type discriminators +- The codebase uses kotlinx.serialization for JSON encoding/decoding with custom serializers for versioned state objects +- Test assertions need to compare expected JSON structure against actual serializer output without string-based comparison fragility +- The buildJsonObject DSL with put operations provides type-safe construction of expected JSON structures for assertion matching + +## Problem Statement + +Test assertions for JSON serialization require a reliable method to construct expected JSON structures that can be compared against actual serializer output. String-based JSON comparison is fragile and difficult to maintain, while manual JsonObject construction is verbose and error-prone. A standardized approach is needed to build expected JSON structures in tests that is both readable and type-safe. + +## Decision + +1. MUST: JSON object construction in tests MUST use the put function to add key-value pairs within buildJsonObject blocks + +## Policy Block + +- MUST JSON object construction in tests MUST use the put function to add key-value pairs within buildJsonObject blocks + +## Rationale + +- The pattern appears in 2 test files with 91.70% confidence, both using buildJsonObject with put operations for JSON assertion construction +- WrappedAccountCryptographicStateSerializerTest demonstrates the pattern for versioned state objects (V1, V2) with type discriminators +- VaultSdkPolicyExtensionsTest shows the pattern applied to SDK policy conversion testing with empty list and multi-item list scenarios +- The kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put functions provide the DSL foundation for this testing approach + +## Consequences + +Positive: +- Type-safe JSON construction in tests reduces runtime errors from malformed JSON strings +- DSL syntax improves test readability by making JSON structure explicit and self-documenting +- Refactoring serialization logic becomes safer as tests clearly express expected structure +- IDE support for DSL provides autocomplete and type checking during test development + +Negative: +- Developers must learn kotlinx.serialization DSL syntax in addition to standard assertion libraries +- Verbose buildJsonObject blocks may increase test code size compared to raw JSON strings +- Pattern creates coupling to kotlinx.serialization library for test infrastructure +- Complex nested JSON structures may become difficult to read despite DSL benefits + +## Alternatives + +- Use raw JSON strings with Json.parseToJsonElement for expected values (rejected) + Rejected because: String-based JSON is fragile, lacks type safety, and requires manual escaping of special characters + When valid: Acceptable for simple one-off tests where JSON structure is trivial and unlikely to change +- Construct JsonObject instances directly using JsonObject constructor (rejected) + Rejected because: Direct constructor usage is verbose and less readable than DSL syntax, reducing test maintainability + When valid: Valid when buildJsonObject DSL is unavailable or when programmatic construction is required +- Use snapshot testing to capture serialized JSON output (deferred) + Rejected because: Not rejected but deferred; snapshot testing complements rather than replaces structural assertions + When valid: Useful for regression testing of large JSON structures where exact structure verification is needed + +## Risks + +- DSL syntax changes in kotlinx.serialization updates could break existing tests + Mitigation: Pin kotlinx.serialization version and review release notes before upgrades; maintain test suite coverage + Owner: engineering team +- Overuse of buildJsonObject for simple assertions may reduce test clarity + Mitigation: Establish guidelines for when DSL is appropriate versus simpler assertion methods; code review enforcement + Owner: engineering team +- New team members unfamiliar with kotlinx.serialization DSL may write inconsistent tests + Mitigation: Document pattern in testing guidelines; provide examples in test templates; conduct code review training + Owner: engineering team + +## Implementation Notes + +- Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern +- Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order +- For versioned state objects, always verify the type discriminator field first in the buildJsonObject block +- Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests + +## Continuation Context + + +Verify commands: +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l +- grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' +- ./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' + +Accept when: +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output + +## Enforcement + +- Verified by: Code review checklist requiring buildJsonObject usage in serialization tests +- Verified by: Static analysis or linting rules detecting raw JSON strings in test assertions +- Verified by: CI pipeline test execution validating serialization test coverage +- Violation handling: Code review feedback requesting refactoring to buildJsonObject DSL +- Violation handling: Pull request comments with examples of correct pattern usage +- Violation handling: Test failures flagged for investigation if serialization assertions use non-standard approaches +- Exception process: Document rationale in test comments when alternative assertion method is necessary +- Exception process: Obtain approval from tech lead for exceptions in complex or legacy test scenarios +- Exception process: Track exceptions in testing guidelines document with justification and review date \ No newline at end of file diff --git a/docs/adr/668b18be-602f-4256-9ff1-cdb73bd4329a-adopt-hilt-dependency-injection-for-android-application-components-android-activity-components.md b/docs/adr/668b18be-602f-4256-9ff1-cdb73bd4329a-adopt-hilt-dependency-injection-for-android-application-components-android-activity-components.md new file mode 100644 index 00000000000..63e02cc520c --- /dev/null +++ b/docs/adr/668b18be-602f-4256-9ff1-cdb73bd4329a-adopt-hilt-dependency-injection-for-android-application-components-android-activity-components.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Android Activity Components + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. MUST: All Android Activity components MUST be annotated with @AndroidEntryPoint to enable Hilt dependency injection + +## Policy Block + +- MUST All Android Activity components MUST be annotated with @AndroidEntryPoint to enable Hilt dependency injection + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/66c4ea0f-5e64-4cdc-bb11-8ae3cdb5c69b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-inject-savedstatehandle.md b/docs/adr/66c4ea0f-5e64-4cdc-bb11-8ae3cdb5c69b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-inject-savedstatehandle.md new file mode 100644 index 00000000000..de03a1cf422 --- /dev/null +++ b/docs/adr/66c4ea0f-5e64-4cdc-bb11-8ae3cdb5c69b-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-inject-savedstatehandle.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Inject Savedstatehandle + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. MAY: ViewModels MAY inject SavedStateHandle to access navigation arguments and persist state across process death + +## Policy Block + +- MAY ViewModels MAY inject SavedStateHandle to access navigation arguments and persist state across process death + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/67b3466d-4c62-4a90-8600-c539cf78d7c4-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-public-boundaries.md b/docs/adr/67b3466d-4c62-4a90-8600-c539cf78d7c4-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-public-boundaries.md new file mode 100644 index 00000000000..dff8e086151 --- /dev/null +++ b/docs/adr/67b3466d-4c62-4a90-8600-c539cf78d7c4-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-public-boundaries.md @@ -0,0 +1,116 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Public Boundaries + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Three ViewModel implementations (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel) consistently use HiltViewModel annotation for dependency injection at public API boundaries handling Android Intent-based interactions +- All three ViewModels extend BaseViewModel and coordinate external API contracts through sealed action types (CredentialProviderAction, AuthCallbackAction) and data classes for Intent processing +- The pattern appears in ViewModels managing authentication flows, credential provider operations, and autofill callbacks, indicating a standardized approach to handling Android system integration points +- Dependencies injected include AuthRepository, BitwardenCredentialManager, and CredentialProviderRequestManager, suggesting a consistent architectural layer for external API coordination + +## Problem Statement + +Android ViewModels serving as public API boundaries for system integrations (credential providers, authentication callbacks, autofill) require consistent dependency injection to ensure testability, lifecycle management, and separation of concerns. Without a standardized DI approach, these critical integration points risk inconsistent initialization, difficult testing, and tight coupling to Android framework components. + +## Decision + +1. MUST: ViewModels at public API boundaries MUST extend BaseViewModel to ensure consistent lifecycle and state management + +## Policy Block + +- MUST ViewModels at public API boundaries MUST extend BaseViewModel to ensure consistent lifecycle and state management + +In scope: +- Android ViewModels handling credential provider APIs +- ViewModels processing authentication callback Intents +- ViewModels coordinating autofill service interactions +- Any ViewModel serving as boundary between Android system services and application logic + +Out of scope: +- Internal ViewModels not exposed to Android system APIs +- Fragment or Activity ViewModels handling only UI state +- Repository or manager layer components +- Non-Android platform integrations + +Exceptions: +- EXC-001: Legacy ViewModels predating Hilt adoption that require gradual migration + +## Rationale + +- Evidence shows 100% consistency across three distinct public API boundary ViewModels (credential provider, auth callback, autofill), indicating an established architectural pattern with 91.70% confidence +- HiltViewModel annotation provides Android-aware dependency injection that respects ViewModel lifecycle and survives configuration changes, critical for Intent-based system integrations +- Sealed action types and data classes create type-safe contracts that prevent runtime errors at public API boundaries where external systems interact with application logic +- Injected repository and manager components enable testability by allowing mock implementations during unit testing of Intent processing logic + +## Consequences + +Positive: +- Consistent dependency injection pattern across all public API boundary ViewModels improves maintainability and reduces cognitive load +- HiltViewModel lifecycle management prevents memory leaks and ensures proper cleanup of resources during configuration changes +- Testability improves through constructor injection, enabling unit tests with mock repositories without Android framework dependencies +- Type-safe sealed action contracts prevent runtime errors from malformed Intent data at system integration boundaries + +Negative: +- Introduces Hilt framework dependency for all public API ViewModels, increasing build complexity and annotation processing time +- Developers must understand Hilt scoping and lifecycle rules to correctly implement ViewModels at public API boundaries +- Migration of existing ViewModels to HiltViewModel pattern requires refactoring and testing effort +- Sealed action types increase boilerplate code compared to direct Intent parameter passing + +## Alternatives + +- Use manual ViewModel factory pattern with direct constructor injection (rejected) + Rejected because: Manual factory pattern requires boilerplate for each ViewModel and does not integrate with Android lifecycle-aware components as seamlessly as Hilt + When valid: In projects without Hilt or when minimizing annotation processing overhead is critical +- Use Dagger without Hilt for ViewModel injection (rejected) + Rejected because: Dagger alone requires more boilerplate and manual component management compared to Hilt's Android-specific optimizations + When valid: In projects with existing Dagger infrastructure where Hilt migration cost is prohibitive +- Use service locator pattern for dependency resolution in ViewModels (rejected) + Rejected because: Service locator pattern hides dependencies, reduces testability, and creates runtime dependency resolution failures instead of compile-time errors + When valid: Never recommended for new code; only acceptable in legacy codebases during gradual migration + +## Risks + +- Hilt annotation processing failures could break builds for all public API ViewModels simultaneously + Mitigation: Maintain Hilt version compatibility matrix, use Gradle dependency locking, and implement CI build verification for annotation processing + Owner: Engineering team +- Developers unfamiliar with Hilt may incorrectly scope dependencies, causing memory leaks or premature disposal + Mitigation: Provide ViewModel dependency injection guidelines, code review checklist, and automated lint rules to detect incorrect scoping + Owner: Architecture team +- Sealed action types may grow complex as public API contracts evolve, reducing maintainability + Mitigation: Establish action type design guidelines limiting nesting depth, use composition over inheritance, and refactor when action hierarchies exceed three levels + Owner: Engineering team + +## Implementation Notes + +- Annotate all public API boundary ViewModels with @HiltViewModel and ensure constructor parameters are annotated with @Inject +- Define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic +- Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel +- Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l +- grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l +- find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l + +Accept when: +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters + +## Enforcement + +- Verified by: Code review checklist requiring HiltViewModel annotation for all public API boundary ViewModels +- Verified by: Custom lint rule detecting ViewModels with Intent parameters lacking @HiltViewModel annotation +- Verified by: CI pipeline verification step running grep commands to validate pattern compliance +- Violation handling: CI build fails if public API ViewModels lack @HiltViewModel annotation +- Violation handling: Code review blocks merge if sealed action types are not used for Intent-based contracts +- Violation handling: Architecture team notified of violations for pattern compliance tracking +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in ADR exceptions registry with approval date and review schedule +- Exception process: Re-evaluate exception quarterly to assess migration feasibility \ No newline at end of file diff --git a/docs/adr/68f32bb1-c4fa-4894-a34c-c2b358509119-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-component-functions-that.md b/docs/adr/68f32bb1-c4fa-4894-a34c-c2b358509119-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-component-functions-that.md new file mode 100644 index 00000000000..ef531923fd2 --- /dev/null +++ b/docs/adr/68f32bb1-c4fa-4894-a34c-c2b358509119-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-component-functions-that.md @@ -0,0 +1,123 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Component Functions That + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all UI component development in the Android application codebase. + +## Context + +- The Android application uses Jetpack Compose as the declarative UI framework, requiring the @Composable annotation to mark functions that emit UI elements +- Three screen implementation files in the auth feature module (SetupUnlockScreen.kt, ExpiredRegistrationLinkScreen.kt, CompleteRegistrationHandler.kt) consistently use @Composable functions with androidx.compose.* foundation and runtime libraries +- The codebase demonstrates a pattern of composing UI hierarchies using androidx.compose.foundation.layout components (Column, Row, Spacer) and androidx.compose.runtime utilities (remember, Composable) +- The detection spans authentication-related UI screens, indicating organization-wide adoption of Compose for user-facing interface construction + +## Problem Statement + +Android UI development requires a consistent framework for declaring composable UI components that integrate with the Jetpack Compose runtime, ensuring proper recomposition behavior, state management, and layout composition across all screen implementations. + +## Decision + +1. MUST: All UI component functions that emit visual elements MUST be annotated with @Composable from androidx.compose.runtime + +## Policy Block + +- MUST All UI component functions that emit visual elements MUST be annotated with @Composable from androidx.compose.runtime + +In scope: +- All Android UI screen implementations in app/src/main/kotlin UI packages +- Authentication feature module UI components +- Any function that directly or indirectly emits Compose UI elements +- Handler components that coordinate UI composition with ViewModels + +Out of scope: +- ViewModel classes and business logic layers +- Data repository and network layer implementations +- Utility functions that do not emit UI +- Android View system components (legacy XML-based UI) +- Unit test files and test utilities + +Exceptions: +- EXC-001: Interoperating with legacy Android View system components during migration +- EXC-002: Preview functions for Android Studio Compose preview tooling + +## Rationale + +- Evidence from 3 files shows consistent use of @Composable annotation with 92.50% confidence, indicating established organizational practice +- Jetpack Compose provides declarative UI construction with automatic recomposition, reducing boilerplate and state synchronization complexity compared to imperative View system +- The androidx.compose.foundation and androidx.compose.runtime libraries form the core dependency set observed across all detected files, establishing a stable API surface +- Standardizing on @Composable annotation ensures compile-time verification of composable function constraints and enables Compose compiler optimizations + +## Consequences + +Positive: +- Declarative UI composition reduces state management complexity and eliminates manual view updates +- Compose compiler enforces composable function constraints at compile-time, catching errors early +- Consistent use of androidx.compose.* libraries provides a unified API surface for UI development +- Improved developer productivity through reduced boilerplate and better tooling support (preview, inspection) + +Negative: +- Requires learning curve for developers familiar with traditional Android View system +- Increases APK size due to Compose runtime library dependencies +- Limited interoperability with legacy View-based components requires AndroidView wrappers +- Compose compiler plugin adds build time overhead for annotation processing + +## Alternatives + +- Continue using traditional Android View system with XML layouts and findViewById (rejected) + Rejected because: Imperative View system requires manual state synchronization, increases boilerplate, and lacks compile-time UI verification. Evidence shows organization has already committed to Compose. + When valid: Only for legacy modules not yet migrated or when specific View components have no Compose equivalent +- Adopt alternative declarative UI frameworks (Flutter, React Native) (rejected) + Rejected because: Would require complete platform rewrite and abandonment of native Android tooling. Evidence shows deep integration with androidx.compose.* libraries. + When valid: For new greenfield projects with cross-platform requirements from inception +- Hybrid approach mixing Compose and View system components (deferred) + Rejected because: Not rejected but deferred as a migration strategy. Evidence shows pure Compose adoption in detected files. + When valid: During migration period for legacy screens not yet converted to Compose + +## Risks + +- Compose API instability or breaking changes in androidx.compose.* libraries during version upgrades + Mitigation: Pin Compose library versions in dependency management, test thoroughly before upgrading, monitor Compose release notes + Owner: Android platform team +- Performance degradation from excessive recomposition in complex UI hierarchies + Mitigation: Use remember, derivedStateOf, and key() appropriately, profile with Compose Layout Inspector, follow Compose performance best practices + Owner: Engineering team +- Developer knowledge gap leading to anti-patterns or misuse of Composable functions + Mitigation: Provide Compose training, establish code review guidelines, create internal documentation and examples + Owner: Engineering team and tech leads + +## Implementation Notes + +- Import androidx.compose.runtime.Composable explicitly in all UI component files +- Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives +- Integrate androidx.compose.runtime.remember for state that should survive recomposition +- Follow naming convention of PascalCase for Composable functions to distinguish from regular functions +- Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l +- grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l +- find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation (verify via static analysis or code review) + +## Enforcement + +- Verified by: Automated static analysis via Compose compiler checks during build +- Verified by: Code review checklist requiring @Composable annotation for UI functions +- Verified by: CI pipeline grep verification counting @Composable usage in UI packages +- Violation handling: Build failure if Composable functions violate compiler constraints (e.g., calling composables from non-composable context) +- Violation handling: Code review rejection for UI functions missing @Composable annotation +- Violation handling: Automated linting warnings for missing androidx.compose.runtime.Composable imports +- Exception process: Submit exception request to architecture team with justification for non-Compose UI approach +- Exception process: Document legacy View system usage in migration tracking system +- Exception process: Obtain approval from tech lead for interop scenarios requiring AndroidView wrappers \ No newline at end of file diff --git a/docs/adr/6b752b5a-f0df-4dce-ad73-38ba239f157b-adopt-unittest-and-vitest-as-standard-testing-frameworks-tests-verify-both.md b/docs/adr/6b752b5a-f0df-4dce-ad73-38ba239f157b-adopt-unittest-and-vitest-as-standard-testing-frameworks-tests-verify-both.md new file mode 100644 index 00000000000..861b74b14d5 --- /dev/null +++ b/docs/adr/6b752b5a-f0df-4dce-ad73-38ba239f157b-adopt-unittest-and-vitest-as-standard-testing-frameworks-tests-verify-both.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Tests Verify Both + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. MUST: Tests MUST verify both positive cases (valid inputs) and negative cases (invalid inputs) + +## Policy Block + +- MUST Tests MUST verify both positive cases (valid inputs) and negative cases (invalid inputs) + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/6be14423-e197-4c2d-b1a4-364a8e436a4c-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-scripts-use-predicate.md b/docs/adr/6be14423-e197-4c2d-b1a4-364a8e436a4c-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-scripts-use-predicate.md new file mode 100644 index 00000000000..2c3ede546c0 --- /dev/null +++ b/docs/adr/6be14423-e197-4c2d-b1a4-364a8e436a4c-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-scripts-use-predicate.md @@ -0,0 +1,118 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Scripts Use Predicate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test specifications and automation scripts across the codebase demonstrate consistent patterns of importing core libraries (vitest, node:fs, node:path, argparse, json, sys, os) and performing data access operations using collection methods like find(), add(), and load(). +- The pattern emerges in three distinct contexts: TypeScript test files using vitest for parsing dumpsys output, Python scripts for GitHub PR labeling automation, and Python scripts for JSON validation, indicating a cross-language consistency in data access approaches. +- Data access patterns consistently involve in-memory collection operations (Set.add(), Array.find()) and file-based JSON loading (json.load(f)), suggesting a preference for simple, direct data manipulation over abstraction layers. +- The detection spans test frameworks (describe, it), standard library imports (node:fs, node:path, argparse, json, sys, os), and runtime libraries (vitest), indicating these are foundational dependencies for testing and automation workflows. + +## Problem Statement + +The codebase lacks explicit guidance on which core libraries and data access patterns should be used for test specifications and automation scripts, leading to potential inconsistency in how data is loaded, queried, and manipulated across different modules and languages. + +## Decision + +1. MAY: Scripts MAY use predicate-based filtering with Array.find() and lambda expressions for locating specific data elements within collections. + +## Policy Block + +- MAY Scripts MAY use predicate-based filtering with Array.find() and lambda expressions for locating specific data elements within collections. + +In scope: +- Test specification files (*.spec.ts, *.test.ts) +- Automation scripts in .github/scripts/ +- Validation and parsing utilities +- CI/CD pipeline scripts + +Out of scope: +- Production application code with complex query requirements +- Database access layers requiring ORM or query builders +- High-performance data processing pipelines +- Browser-based test runners (e.g., Playwright, Cypress) + +Exceptions: +- EXC-001: Performance profiling indicates native collection methods create bottlenecks in large dataset processing +- EXC-002: External API contracts require specific JSON schema validation libraries beyond standard json module capabilities + +## Rationale + +- The evidence shows consistent use of standard library modules across 3 files with 90.83% confidence, indicating an established pattern that minimizes external dependencies and reduces maintenance burden. +- Using native collection methods (find(), add()) and standard library JSON parsing provides predictable behavior, reduces bundle size, and eliminates version compatibility issues with third-party libraries. +- The pattern spans both TypeScript (vitest, node:fs, node:path) and Python (json, sys, os, argparse) contexts, demonstrating language-appropriate choices that align with ecosystem conventions. +- Direct data access patterns without abstraction layers are appropriate for the observed use cases (test parsing, label automation, JSON validation) where query complexity is low and transparency is valuable. + +## Consequences + +Positive: +- Reduced dependency footprint in test and automation scripts, minimizing security surface area and dependency update overhead +- Improved script portability and long-term maintainability by relying on stable standard library APIs rather than third-party package ecosystems +- Lower cognitive overhead for developers familiar with standard library APIs, reducing onboarding time for test and automation contributions +- Faster script execution and smaller bundle sizes due to elimination of unnecessary abstraction layers + +Negative: +- Limited query expressiveness for complex data access patterns, requiring manual predicate logic rather than declarative query syntax +- Potential code duplication if similar data access patterns are repeated across multiple scripts without shared utility functions +- Lack of type safety in Python json.load() operations without additional validation layers or schema enforcement +- Manual error handling required for file I/O and JSON parsing operations without framework-provided retry or validation mechanisms + +## Alternatives + +- Adopt lodash/underscore for collection operations and data manipulation in both TypeScript and Python scripts (rejected) + Rejected because: Evidence shows native methods (Array.find(), Set.add()) are sufficient for current use cases; adding lodash would increase bundle size and introduce unnecessary dependency without demonstrated performance or expressiveness benefits + When valid: Valid for scripts processing large datasets requiring complex transformations like groupBy, partition, or deep merging +- Use Pydantic or JSON Schema validators for structured JSON validation instead of raw json.load() (deferred) + Rejected because: Current validation scripts use simple duplicate detection and basic structure checks; schema validation libraries add complexity without clear evidence of validation requirements beyond basic parsing + When valid: Valid when external API contracts require strict schema enforcement or when validation error messages need to be user-facing +- Standardize on Jest instead of vitest for TypeScript test specifications (rejected) + Rejected because: Evidence explicitly shows vitest usage in test specifications; Jest would require migration effort and vitest provides faster execution with native ESM support + When valid: Valid for projects requiring Jest-specific ecosystem plugins or snapshot testing features not available in vitest + +## Risks + +- Scripts may grow complex enough that native collection methods become verbose and error-prone, leading to maintenance burden + Mitigation: Establish shared utility modules for common data access patterns; set complexity threshold (e.g., >3 nested loops) triggering refactor to query library + Owner: Engineering team +- Lack of schema validation in JSON loading may allow malformed data to propagate through automation pipelines, causing runtime failures + Mitigation: Add explicit validation checks after json.load() for critical fields; document expected JSON structure in script docstrings; consider schema validation for external data sources + Owner: DevOps and automation team +- Standard library file I/O patterns may not handle edge cases (encoding issues, large files, concurrent access) as robustly as specialized libraries + Mitigation: Document encoding assumptions (UTF-8) explicitly; add file size checks for large file handling; use file locking for concurrent access scenarios + Owner: Engineering team + +## Implementation Notes + +- Create shared utility modules for common patterns: parseJsonFile(), findInCollection(), addToSet() to reduce duplication while maintaining standard library usage +- Add ESLint/Pylint rules to flag imports of lodash, ramda, or other collection libraries in test and automation script directories +- Document standard library API patterns in developer guide with examples from existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) +- For new automation scripts, use existing scripts as templates to ensure consistency in import patterns and data access approaches + +## Continuation Context + + +Verify commands: +- grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l +- grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l +- grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l +- grep -r "\.find(\|.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +Accept when: +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts + +## Enforcement + +- Verified by: CI pipeline static analysis checking for prohibited third-party imports in test and automation script directories +- Verified by: Code review checklist item verifying standard library usage for new test specifications and automation scripts +- Verified by: Automated dependency audits flagging new dependencies in package.json or requirements.txt within scope directories +- Violation handling: CI build fails if prohibited imports (lodash, ramda, etc.) are detected in test or automation scripts +- Violation handling: Pull requests adding external dependencies to automation scripts require architecture review and explicit justification +- Violation handling: Existing violations are tracked in technical debt backlog with migration plan to standard library equivalents +- Exception process: Submit exception request to tech lead with performance benchmarks or capability gap analysis +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration criteria +- Exception process: Review exceptions quarterly to assess if standard library improvements or refactoring can eliminate the need \ No newline at end of file diff --git a/docs/adr/6e3e1b7f-9835-4724-84f8-c348d80e4aef-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-classes.md b/docs/adr/6e3e1b7f-9835-4724-84f8-c348d80e4aef-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-classes.md new file mode 100644 index 00000000000..a12ecb954a4 --- /dev/null +++ b/docs/adr/6e3e1b7f-9835-4724-84f8-c348d80e4aef-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-classes.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Python Test Classes + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. SHOULD: Python test classes SHOULD implement setUp and tearDown methods for test fixture initialization and cleanup when shared state is required + +## Policy Block + +- SHOULD Python test classes SHOULD implement setUp and tearDown methods for test fixture initialization and cleanup when shared state is required + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/722f54e6-84df-4098-bb25-b1a404fd7445-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-error-logging.md b/docs/adr/722f54e6-84df-4098-bb25-b1a404fd7445-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-error-logging.md new file mode 100644 index 00000000000..a3f8b69d208 --- /dev/null +++ b/docs/adr/722f54e6-84df-4098-bb25-b1a404fd7445-standardize-console-error-and-response-error-for-error-logging-in-libraries-library-error-logging.md @@ -0,0 +1,117 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Library Error Logging + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Library modules in both TypeScript (android-device-server) and Kotlin (bitwarden network layer) implement error logging using platform-native error reporting mechanisms +- The TypeScript implementation uses console.error for tool errors and fatal errors in an MCP server context, while the Kotlin implementation uses Response.error with HTTP status codes and JSON-formatted error messages +- Both implementations integrate error logging within core library functionality, suggesting a cross-platform pattern for observable error handling in modular architectures +- The pattern appears in libraries that serve as integration points: an Android device MCP server and a network layer for API communication + +## Problem Statement + +Library modules require consistent, observable error logging mechanisms that integrate with their respective runtime environments (Node.js console for TypeScript, Retrofit Response for Kotlin) to enable debugging, monitoring, and error propagation without introducing external logging framework dependencies. + +## Decision + +1. MUST_NOT: Library error logging MUST NOT depend on application-specific logging frameworks or configurations that would create tight coupling between library and consumer + +## Policy Block + +- MUST_NOT Library error logging MUST NOT depend on application-specific logging frameworks or configurations that would create tight coupling between library and consumer + +In scope: +- TypeScript libraries running in Node.js environments with console API access +- Kotlin libraries using Retrofit for HTTP client functionality +- Library modules designed for reuse across multiple applications or services +- Error handling code paths within library boundaries + +Out of scope: +- Application-level logging infrastructure and aggregation systems +- Structured logging frameworks (Winston, Log4j, SLF4J) used by consuming applications +- Production monitoring and alerting systems external to library code +- Log persistence, rotation, or archival mechanisms + +Exceptions: +- EXC-001: Library is explicitly designed as a logging abstraction or wrapper (e.g., a logging facade library) +- EXC-002: Library operates in an environment without platform-native error logging (embedded systems, constrained runtimes) + +## Rationale + +- Platform-native error logging mechanisms (console.error, Response.error) are universally available in their respective runtime environments, eliminating external dependencies and reducing library footprint +- The pattern observed across TypeScript and Kotlin implementations demonstrates a cross-platform architectural principle: libraries should use runtime-provided error reporting rather than introducing framework coupling +- Using platform-native mechanisms enables library consumers to intercept, redirect, or enhance error logging through standard runtime hooks (console redirection, Retrofit interceptors) without modifying library code +- The evidence shows consistent integration of error logging with core library operations (tool execution, HTTP response construction), indicating error observability is treated as a first-class concern in library design + +## Consequences + +Positive: +- Reduced library dependency footprint by avoiding external logging framework dependencies +- Improved library portability across different application contexts and deployment environments +- Simplified library testing through standard console/response mocking mechanisms +- Enhanced consumer flexibility to integrate library error logging with application-specific monitoring infrastructure + +Negative: +- Limited structured logging capabilities compared to dedicated logging frameworks (no log levels, structured fields, or filtering) +- Potential inconsistency in error log format across different libraries and platforms +- Reduced observability features such as automatic context propagation, correlation IDs, or distributed tracing integration +- Console.error output may be difficult to parse or aggregate in production monitoring systems without additional tooling + +## Alternatives + +- Adopt a lightweight, cross-platform logging abstraction library (e.g., pino for TypeScript, SLF4J for Kotlin) as a standard dependency (rejected) + Rejected because: Introduces external dependency and version management complexity; conflicts with the observed pattern of using platform-native mechanisms; reduces library portability + When valid: When libraries require structured logging with log levels, filtering, and production-grade observability features that justify the dependency cost +- Implement custom logging abstraction within each library with pluggable backends (rejected) + Rejected because: Increases library code complexity and maintenance burden; duplicates logging abstraction logic across libraries; evidence shows preference for simple, direct error reporting + When valid: When building a library ecosystem with shared logging requirements and centralized logging infrastructure management +- Provide optional logging callback parameters for all error-prone operations (deferred) + Rejected because: Not observed in current evidence; would require API design changes across library interfaces + When valid: As an enhancement to enable custom error handling while maintaining platform-native defaults (see R-20-006) + +## Risks + +- Inconsistent error log formats across libraries make centralized monitoring and alerting difficult to implement + Mitigation: Establish error message format conventions (e.g., prefix patterns, JSON structure) documented in library development guidelines; provide examples of log parsing patterns for common monitoring tools + Owner: Engineering team, library maintainers +- Platform-native error logging may not provide sufficient detail for debugging complex library interactions in production + Mitigation: Ensure error messages include actionable context (operation name, input parameters, error codes); document error scenarios and troubleshooting steps in library documentation; consider optional verbose logging modes + Owner: Engineering team +- Console.error output in high-throughput scenarios may impact performance or overwhelm log aggregation systems + Mitigation: Implement error rate limiting or sampling for repetitive errors; document expected error logging volume in library performance characteristics; provide guidance on console redirection for production environments + Owner: Engineering team, SRE team + +## Implementation Notes + +- For TypeScript libraries, use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin network libraries using Retrofit, construct Response.error with appropriate HTTP status codes (e.g., HTTP_CODE_BAD_REQUEST) and JSON-formatted error messages using ResponseBody.Companion.toResponseBody +- Include sufficient context in error messages to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes +- Document expected error log output format and examples in library README to help consumers implement log parsing and monitoring + +## Continuation Context + + +Verify commands: +- grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" +- grep -r "Response\.error" --include="*.kt" src/ | head -20 +- grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l + +Accept when: +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + +## Enforcement + +- Verified by: Code review checklist verifying use of platform-native error logging mechanisms +- Verified by: Dependency analysis in CI pipeline flagging external logging framework dependencies in library modules +- Verified by: Grep-based verification commands checking for console.error and Response.error patterns in library code +- Violation handling: Code review feedback requesting removal of external logging framework dependencies and migration to platform-native mechanisms +- Violation handling: CI pipeline warnings when external logging dependencies are detected in library package manifests +- Violation handling: Architecture review required for libraries that cannot use platform-native error logging due to runtime constraints +- Exception process: Submit exception request documenting runtime environment constraints or logging requirements that cannot be met with platform-native mechanisms +- Exception process: Technical lead or architecture review approval required for exception +- Exception process: Document approved exceptions in library README with justification and alternative error reporting mechanism details \ No newline at end of file diff --git a/docs/adr/72ef156e-bd9d-4bad-87fc-e4ecb337b03e-adopt-zod-schema-validation-for-tool-input-parameters-timing-parameters-waitseconds.md b/docs/adr/72ef156e-bd9d-4bad-87fc-e4ecb337b03e-adopt-zod-schema-validation-for-tool-input-parameters-timing-parameters-waitseconds.md new file mode 100644 index 00000000000..0b84967711d --- /dev/null +++ b/docs/adr/72ef156e-bd9d-4bad-87fc-e4ecb337b03e-adopt-zod-schema-validation-for-tool-input-parameters-timing-parameters-waitseconds.md @@ -0,0 +1,116 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Timing Parameters Waitseconds + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the Android Device Server MCP that accept external input parameters. + +## Context + +- The Android Device Server MCP exposes tool handlers that accept external input from clients, requiring validation to prevent invalid operations and runtime errors +- Tool parameters include coordinates, timing values, and boolean flags that must conform to specific constraints (non-negative integers, minimum values, type safety) +- The codebase imports 'zod' as a core dependency and '../utils/validation.js' across multiple tool implementations, indicating a standardized validation approach +- Two tool handlers (capture.ts and tap-at.ts) demonstrate consistent schema definition patterns using z.object() with typed field validators + +## Problem Statement + +Tool handlers in the Android Device Server MCP must validate external input parameters to ensure type safety, enforce domain constraints (e.g., non-negative coordinates, valid timing ranges), and prevent invalid ADB commands from being executed, but without a standardized validation approach, each tool would implement ad-hoc validation logic leading to inconsistency and maintenance burden. + +## Decision + +1. MUST: Timing parameters (waitSeconds, delays) MUST be validated with minimum value constraints using z.number().min() + +## Policy Block + +- MUST Timing parameters (waitSeconds, delays) MUST be validated with minimum value constraints using z.number().min() + +In scope: +- All tool handler implementations in src/tools/ that accept external parameters +- Input validation for ADB command parameters (coordinates, timing, flags) +- Public API contracts exposed through MCP tool interfaces + +Out of scope: +- Internal utility functions that do not accept external input +- ADB command output parsing and response formatting +- Device discovery and connection management logic + +## Rationale + +- The evidence shows consistent use of Zod schemas across capture.ts and tap-at.ts with identical import patterns ('zod', '../utils/validation.js'), indicating an established validation standard +- Schema definitions enforce domain-specific constraints (non-negative coordinates, minimum timing values) that prevent invalid ADB commands and improve system reliability +- Centralized validation through Zod provides type inference, runtime validation, and clear error messages, reducing boilerplate and improving developer experience +- The pattern appears in the security.input_validation facet with 91.20% confidence across 2 files, demonstrating measurable adoption + +## Consequences + +Positive: +- Type-safe input validation with automatic TypeScript type inference from schemas +- Consistent validation error messages and handling across all tool implementations +- Reduced boilerplate code compared to manual parameter checking and validation +- Clear API contracts that are self-documenting through schema definitions + +Negative: +- Additional runtime overhead for schema validation on every tool invocation +- Dependency on the Zod library increases bundle size and introduces external maintenance risk +- Developers must learn Zod API and schema composition patterns +- Schema definitions add verbosity to tool handler implementations + +## Alternatives + +- Manual parameter validation using TypeScript type guards and conditional checks (rejected) + Rejected because: Leads to inconsistent validation logic, verbose boilerplate, and no runtime type safety guarantees + When valid: For simple internal functions with minimal validation requirements +- Use JSON Schema with ajv validator for runtime validation (rejected) + Rejected because: Requires separate type definitions and schema definitions, losing TypeScript type inference benefits + When valid: When interoperating with systems that already use JSON Schema standards +- Use io-ts for functional programming style validation (rejected) + Rejected because: Steeper learning curve and more verbose syntax compared to Zod's developer-friendly API + When valid: In codebases with strong functional programming conventions using fp-ts + +## Risks + +- Zod library vulnerabilities or breaking changes in future versions could impact all tool handlers + Mitigation: Pin Zod version in package.json, monitor security advisories, and maintain comprehensive test coverage for validation logic + Owner: engineering team +- Complex nested schemas may introduce performance bottlenecks for high-frequency tool invocations + Mitigation: Profile validation performance, cache parsed schemas, and consider lazy validation for optional deep structures + Owner: engineering team +- Inconsistent schema patterns across tools if validation utilities are not properly documented + Mitigation: Document standard validation patterns in ../utils/validation.js, provide schema templates, and enforce through code review + Owner: engineering team + +## Implementation Notes + +- Import Zod and validation utilities at the top of each tool handler: import { z } from 'zod' and import validation utilities from '../utils/validation.js' +- Define the input schema as a const using z.object() with appropriate field validators before the handler function +- Use .int().nonnegative() for coordinate parameters, .min(0) for timing parameters, and .optional().default() for optional flags +- Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages +- Export the inferred TypeScript type using z.infer for use in function signatures and documentation + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "../utils/validation" .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool handlers in src/tools/ that accept external parameters import 'zod' and define validation schemas +- Grep commands show consistent usage of z.object() schema definitions across tool implementations +- Validation utility imports from '../utils/validation.js' are present in all relevant tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for new tool handlers +- Verified by: Automated grep-based checks in CI pipeline verifying presence of validation imports +- Verified by: TypeScript compilation ensuring type safety through schema inference +- Violation handling: Pull requests adding tool handlers without Zod validation are rejected during code review +- Violation handling: CI pipeline fails if tool files lack required validation imports +- Violation handling: Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation +- Exception process: Exceptions require written justification documenting why Zod validation is inappropriate for the specific use case +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in code comments with reference to approval decision \ No newline at end of file diff --git a/docs/adr/73df07ab-a3ee-4ae4-95f3-55ea8d01548e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-use.md b/docs/adr/73df07ab-a3ee-4ae4-95f3-55ea8d01548e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-use.md new file mode 100644 index 00000000000..0580898883a --- /dev/null +++ b/docs/adr/73df07ab-a3ee-4ae4-95f3-55ea8d01548e-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-screen-implementations-use.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Screen Implementations Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. MUST: All UI screen implementations MUST use @Composable functions as the primary unit of UI composition + +## Policy Block + +- MUST All UI screen implementations MUST use @Composable functions as the primary unit of UI composition + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/772c14d7-cf35-44f6-8d91-f64c403cc25a-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-classes-implement.md b/docs/adr/772c14d7-cf35-44f6-8d91-f64c403cc25a-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-classes-implement.md new file mode 100644 index 00000000000..f353b568e41 --- /dev/null +++ b/docs/adr/772c14d7-cf35-44f6-8d91-f64c403cc25a-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-classes-implement.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Test Classes Implement + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. SHOULD: Test classes SHOULD implement setUp and tearDown methods for test fixture initialization and cleanup + +## Policy Block + +- SHOULD Test classes SHOULD implement setUp and tearDown methods for test fixture initialization and cleanup + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/77336862-f4d2-43f8-9f85-1649fcc3fc0c-standardize-kotlinx-serialization-json-testing-with-type-discriminators-custom-kotlinx-serialization.md b/docs/adr/77336862-f4d2-43f8-9f85-1649fcc3fc0c-standardize-kotlinx-serialization-json-testing-with-type-discriminators-custom-kotlinx-serialization.md new file mode 100644 index 00000000000..9b25f75d658 --- /dev/null +++ b/docs/adr/77336862-f4d2-43f8-9f85-1649fcc3fc0c-standardize-kotlinx-serialization-json-testing-with-type-discriminators-custom-kotlinx-serialization.md @@ -0,0 +1,116 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Custom Kotlinx Serialization + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests validate JSON encoding/decoding behavior at service boundaries where data crosses module or API boundaries +- The codebase uses kotlinx.serialization for JSON serialization with custom serializers for domain models like WrappedAccountCryptographicState +- Type discriminators (e.g., 'v1', 'v2') enable versioned serialization formats to support backward compatibility and schema evolution +- Tests use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings +- The pattern appears in cryptographic state serialization and policy view conversion, indicating cross-cutting serialization concerns + +## Problem Statement + +Service boundaries require reliable serialization contracts that can evolve over time without breaking existing clients. Without standardized testing of JSON serialization including type discriminators and property mappings, schema changes may introduce silent data corruption or deserialization failures at runtime. + +## Decision + +1. MUST: All custom kotlinx.serialization serializers MUST have corresponding test classes that verify JSON encoding produces expected structure + +## Policy Block + +- MUST All custom kotlinx.serialization serializers MUST have corresponding test classes that verify JSON encoding produces expected structure + +In scope: +- Custom kotlinx.serialization serializers for domain models +- Extension functions converting between domain models and SDK types +- JSON encoding/decoding at service and module boundaries +- Versioned serialization formats using type discriminators + +Out of scope: +- Internal data transformations that do not cross serialization boundaries +- Third-party library serializers without custom logic +- Binary serialization formats +- Database entity mappings + +## Rationale + +- The evidence shows consistent use of kotlinx.serialization.json.buildJsonObject and assertEquals patterns across serialization tests, indicating an established testing approach +- Type discriminators ('v1', 'v2') in WrappedAccountCryptographicState tests demonstrate versioning requirements at cryptographic state boundaries +- Tests for toSdkPolicyViews extension function show validation of conversion logic between network models and SDK policy views +- The pattern appears in both data layer (cryptographic state) and vault repository (policy conversion), suggesting cross-cutting serialization concerns requiring standardized testing + +## Consequences + +Positive: +- Serialization contract changes are caught at test time rather than runtime, preventing data corruption +- Type discriminator validation ensures versioned schemas maintain backward compatibility +- Standardized test structure improves maintainability and makes serialization behavior explicit +- Extension function tests verify boundary conversions handle edge cases like empty lists + +Negative: +- Additional test code increases maintenance burden when serialization formats change +- Exact JSON structure assertions are brittle and may require updates for cosmetic changes +- Test duplication across similar serializers may occur without shared test utilities +- Mock factory functions add indirection that may obscure actual test data + +## Alternatives + +- Use property-based testing to verify serialization round-trips without asserting exact JSON structure (rejected) + Rejected because: Does not validate exact JSON contract including field names and discriminator values required for external API compatibility + When valid: Internal serialization where only round-trip fidelity matters, not exact wire format +- Generate serialization tests automatically from schema definitions (deferred) + Rejected because: Requires additional tooling and schema-first development approach not currently in place + When valid: When adopting schema-first API design with OpenAPI or JSON Schema definitions +- Rely on integration tests to catch serialization issues (rejected) + Rejected because: Integration tests are slower, less isolated, and provide poor feedback for serialization contract violations + When valid: Never as sole verification; integration tests complement but do not replace unit-level serialization tests + +## Risks + +- Brittle tests that break on benign JSON formatting changes (e.g., property order) + Mitigation: Use JSON comparison that ignores property order; consider semantic equality checks for non-critical formatting + Owner: engineering team +- Test coverage gaps for deserialization paths and error handling + Mitigation: Extend testing standard to include deserialization tests and malformed input handling + Owner: engineering team +- Type discriminator values may conflict across different serializers + Mitigation: Establish discriminator naming conventions and maintain registry of used discriminator values + Owner: architecture team + +## Implementation Notes + +- Create test classes in src/test/kotlin mirroring the package structure of serializers under test +- Use @Test annotation and assertEquals with buildJsonObject for exact JSON structure validation +- For versioned schemas, create separate test methods for each version verifying the type discriminator field +- When testing extension functions like toSdkPolicyViews, include edge cases such as empty lists and multi-item collections +- Consider extracting mock factory functions (e.g., createMockPolicy) to shared test utilities for reuse across test classes + +## Continuation Context + + +Verify commands: +- grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l +- find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +Accept when: +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + +## Enforcement + +- Verified by: Code review checklist requiring serialization tests for new serializers +- Verified by: CI pipeline test coverage reporting for serialization packages +- Verified by: Static analysis detecting serializers without corresponding test classes +- Violation handling: Pull requests adding serializers without tests are blocked in code review +- Violation handling: Coverage reports flag untested serialization code for remediation +- Violation handling: Architecture review required for serializers lacking discriminator validation +- Exception process: Exceptions require architecture team approval with documented justification +- Exception process: Temporary exceptions must include remediation plan and timeline +- Exception process: Exception requests must demonstrate why alternative testing approach provides equivalent contract validation \ No newline at end of file diff --git a/docs/adr/77bab4bd-ee05-4209-af7b-5c3ed8a41b28-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-dependencies-injected-android.md b/docs/adr/77bab4bd-ee05-4209-af7b-5c3ed8a41b28-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-dependencies-injected-android.md new file mode 100644 index 00000000000..d1521386a5e --- /dev/null +++ b/docs/adr/77bab4bd-ee05-4209-af7b-5c3ed8a41b28-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-dependencies-injected-android.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Dependencies Injected Android + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. MUST: Dependencies injected into Android components MUST be provided through Hilt modules or constructor injection + +## Policy Block + +- MUST Dependencies injected into Android components MUST be provided through Hilt modules or constructor injection + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/791389c7-39fe-4bfe-91d3-16d774336937-standardize-collection-find-pattern-for-in-memory-data-queries-use-alternative-collection.md b/docs/adr/791389c7-39fe-4bfe-91d3-16d774336937-standardize-collection-find-pattern-for-in-memory-data-queries-use-alternative-collection.md new file mode 100644 index 00000000000..eb7878f6fc3 --- /dev/null +++ b/docs/adr/791389c7-39fe-4bfe-91d3-16d774336937-standardize-collection-find-pattern-for-in-memory-data-queries-use-alternative-collection.md @@ -0,0 +1,100 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Use Alternative Collection + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase demonstrates consistent use of JavaScript/TypeScript Array.find() method for querying in-memory collections across test specifications and automation scripts +- Test files in android-device-server use .find() with predicate functions to locate specific window objects by name property from parsed dumpsys output +- Python automation scripts use Set.add() operations for label and package name collection, indicating a pattern of in-memory data accumulation and membership testing +- The pattern appears in both testing contexts (vitest test suites) and operational contexts (GitHub automation scripts, JSON validation utilities) + +## Problem Statement + +Teams need a consistent, predictable approach for querying in-memory data structures to locate specific elements by property matching, particularly when working with parsed system output, configuration data, and test fixtures. Without standardization, different query patterns emerge that reduce code readability and increase cognitive load when navigating between modules. + +## Decision + +1. MAY: Use alternative collection methods (filter, some, every) when query semantics require multiple results or boolean existence checks + +## Policy Block + +- MAY Use alternative collection methods (filter, some, every) when query semantics require multiple results or boolean existence checks + +## Rationale + +- The pattern is observed across 3 files with 90.83% confidence, demonstrating consistent adoption in both test infrastructure and operational automation +- Array.find() provides clear semantic intent for single-element lookup operations, improving code readability compared to manual iteration +- Set.add() operations in Python scripts demonstrate parallel pattern of using language-native collection operations for membership and uniqueness constraints +- The pattern aligns with functional programming principles and modern JavaScript/TypeScript idioms, reducing imperative boilerplate + +## Consequences + +Positive: +- Improved code readability through consistent use of declarative collection query methods +- Reduced cognitive load when navigating between test specifications and automation scripts +- Better alignment with modern JavaScript/TypeScript idioms and functional programming patterns +- Clearer semantic intent in data access operations, making code review and maintenance easier + +Negative: +- Developers unfamiliar with functional array methods may require additional training or documentation +- Predicate function overhead may introduce minor performance cost compared to manual iteration in performance-critical paths +- Pattern may not extend cleanly to languages without first-class function support or equivalent collection APIs + +## Alternatives + +- Use manual for-loop iteration with conditional breaks for element lookup (rejected) + Rejected because: Manual iteration increases boilerplate code and reduces semantic clarity compared to declarative Array.find() method + When valid: Performance-critical paths where predicate function overhead is measured and significant +- Use Array.filter() followed by index access [0] for single-element lookup (rejected) + Rejected because: Array.filter() processes entire collection even after match is found, introducing unnecessary performance overhead + When valid: When subsequent operations require the filtered array or multiple matches are possible +- Use Map or Object lookup with key-based access instead of predicate-based search (deferred) + Rejected because: null + When valid: When data structure can be pre-indexed by lookup key and multiple queries justify indexing overhead + +## Risks + +- Performance degradation in large collections if .find() is used in tight loops or performance-critical paths + Mitigation: Profile data access patterns and consider pre-indexing with Map/Object for frequently queried large collections + Owner: engineering team +- Inconsistent adoption across polyglot codebase where Python, JavaScript, and TypeScript have different collection APIs + Mitigation: Document language-specific equivalents (Python: next(filter()), JavaScript/TypeScript: Array.find()) in coding standards + Owner: engineering team +- Undefined return values from .find() may cause runtime errors if not properly handled with null checks + Mitigation: Enforce TypeScript strict null checks and require explicit undefined handling in code review + Owner: engineering team + +## Implementation Notes + +- Use TypeScript strict mode to enforce null/undefined handling for .find() return values +- Consider creating utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication +- Document the pattern in coding standards with examples from dumpsys.spec.ts showing window lookup by name property +- For Python code, use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find() + +## Continuation Context + + +Verify commands: +- grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . +- grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' +- npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' + +Accept when: +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + +## Enforcement + +- Verified by: Code review checklist includes verification of collection query patterns +- Verified by: ESLint rules configured to discourage manual iteration where Array methods are applicable +- Verified by: Test coverage requirements ensure query operations are tested with expected and missing elements +- Violation handling: Code review feedback requests refactoring of manual iteration to declarative collection methods +- Violation handling: ESLint warnings flagged in CI pipeline for review before merge +- Violation handling: Documentation links provided to developers during code review for pattern examples +- Exception process: Performance-critical paths may use manual iteration if profiling demonstrates measurable impact +- Exception process: Exception requests must include benchmark data comparing Array.find() vs manual iteration +- Exception process: Approved exceptions documented inline with comments explaining performance justification \ No newline at end of file diff --git a/docs/adr/7a73643a-e287-430c-8108-7c1ab4049554-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-memory-data-access.md b/docs/adr/7a73643a-e287-430c-8108-7c1ab4049554-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-memory-data-access.md new file mode 100644 index 00000000000..fd3a0add7d7 --- /dev/null +++ b/docs/adr/7a73643a-e287-430c-8108-7c1ab4049554-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-memory-data-access.md @@ -0,0 +1,118 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Memory Data Access + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test specifications and automation scripts across the codebase demonstrate consistent patterns of importing core libraries (vitest, node:fs, node:path, argparse, json, sys, os) and performing data access operations using collection methods like find(), add(), and load(). +- The pattern emerges in three distinct contexts: TypeScript test files using vitest for parsing dumpsys output, Python scripts for GitHub PR labeling automation, and Python scripts for JSON validation, indicating a cross-language consistency in data access approaches. +- Data access patterns consistently involve in-memory collection operations (Set.add(), Array.find()) and file-based JSON loading (json.load(f)), suggesting a preference for simple, direct data manipulation over abstraction layers. +- The detection spans test frameworks (describe, it), standard library imports (node:fs, node:path, argparse, json, sys, os), and runtime libraries (vitest), indicating these are foundational dependencies for testing and automation workflows. + +## Problem Statement + +The codebase lacks explicit guidance on which core libraries and data access patterns should be used for test specifications and automation scripts, leading to potential inconsistency in how data is loaded, queried, and manipulated across different modules and languages. + +## Decision + +1. SHOULD: In-memory data access operations SHOULD use native collection methods (Array.find(), Set.add()) for querying and mutating data structures rather than introducing query abstraction libraries. + +## Policy Block + +- SHOULD In-memory data access operations SHOULD use native collection methods (Array.find(), Set.add()) for querying and mutating data structures rather than introducing query abstraction libraries. + +In scope: +- Test specification files (*.spec.ts, *.test.ts) +- Automation scripts in .github/scripts/ +- Validation and parsing utilities +- CI/CD pipeline scripts + +Out of scope: +- Production application code with complex query requirements +- Database access layers requiring ORM or query builders +- High-performance data processing pipelines +- Browser-based test runners (e.g., Playwright, Cypress) + +Exceptions: +- EXC-001: Performance profiling indicates native collection methods create bottlenecks in large dataset processing +- EXC-002: External API contracts require specific JSON schema validation libraries beyond standard json module capabilities + +## Rationale + +- The evidence shows consistent use of standard library modules across 3 files with 90.83% confidence, indicating an established pattern that minimizes external dependencies and reduces maintenance burden. +- Using native collection methods (find(), add()) and standard library JSON parsing provides predictable behavior, reduces bundle size, and eliminates version compatibility issues with third-party libraries. +- The pattern spans both TypeScript (vitest, node:fs, node:path) and Python (json, sys, os, argparse) contexts, demonstrating language-appropriate choices that align with ecosystem conventions. +- Direct data access patterns without abstraction layers are appropriate for the observed use cases (test parsing, label automation, JSON validation) where query complexity is low and transparency is valuable. + +## Consequences + +Positive: +- Reduced dependency footprint in test and automation scripts, minimizing security surface area and dependency update overhead +- Improved script portability and long-term maintainability by relying on stable standard library APIs rather than third-party package ecosystems +- Lower cognitive overhead for developers familiar with standard library APIs, reducing onboarding time for test and automation contributions +- Faster script execution and smaller bundle sizes due to elimination of unnecessary abstraction layers + +Negative: +- Limited query expressiveness for complex data access patterns, requiring manual predicate logic rather than declarative query syntax +- Potential code duplication if similar data access patterns are repeated across multiple scripts without shared utility functions +- Lack of type safety in Python json.load() operations without additional validation layers or schema enforcement +- Manual error handling required for file I/O and JSON parsing operations without framework-provided retry or validation mechanisms + +## Alternatives + +- Adopt lodash/underscore for collection operations and data manipulation in both TypeScript and Python scripts (rejected) + Rejected because: Evidence shows native methods (Array.find(), Set.add()) are sufficient for current use cases; adding lodash would increase bundle size and introduce unnecessary dependency without demonstrated performance or expressiveness benefits + When valid: Valid for scripts processing large datasets requiring complex transformations like groupBy, partition, or deep merging +- Use Pydantic or JSON Schema validators for structured JSON validation instead of raw json.load() (deferred) + Rejected because: Current validation scripts use simple duplicate detection and basic structure checks; schema validation libraries add complexity without clear evidence of validation requirements beyond basic parsing + When valid: Valid when external API contracts require strict schema enforcement or when validation error messages need to be user-facing +- Standardize on Jest instead of vitest for TypeScript test specifications (rejected) + Rejected because: Evidence explicitly shows vitest usage in test specifications; Jest would require migration effort and vitest provides faster execution with native ESM support + When valid: Valid for projects requiring Jest-specific ecosystem plugins or snapshot testing features not available in vitest + +## Risks + +- Scripts may grow complex enough that native collection methods become verbose and error-prone, leading to maintenance burden + Mitigation: Establish shared utility modules for common data access patterns; set complexity threshold (e.g., >3 nested loops) triggering refactor to query library + Owner: Engineering team +- Lack of schema validation in JSON loading may allow malformed data to propagate through automation pipelines, causing runtime failures + Mitigation: Add explicit validation checks after json.load() for critical fields; document expected JSON structure in script docstrings; consider schema validation for external data sources + Owner: DevOps and automation team +- Standard library file I/O patterns may not handle edge cases (encoding issues, large files, concurrent access) as robustly as specialized libraries + Mitigation: Document encoding assumptions (UTF-8) explicitly; add file size checks for large file handling; use file locking for concurrent access scenarios + Owner: Engineering team + +## Implementation Notes + +- Create shared utility modules for common patterns: parseJsonFile(), findInCollection(), addToSet() to reduce duplication while maintaining standard library usage +- Add ESLint/Pylint rules to flag imports of lodash, ramda, or other collection libraries in test and automation script directories +- Document standard library API patterns in developer guide with examples from existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) +- For new automation scripts, use existing scripts as templates to ensure consistency in import patterns and data access approaches + +## Continuation Context + + +Verify commands: +- grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l +- grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l +- grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l +- grep -r "\.find(\|.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +Accept when: +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts + +## Enforcement + +- Verified by: CI pipeline static analysis checking for prohibited third-party imports in test and automation script directories +- Verified by: Code review checklist item verifying standard library usage for new test specifications and automation scripts +- Verified by: Automated dependency audits flagging new dependencies in package.json or requirements.txt within scope directories +- Violation handling: CI build fails if prohibited imports (lodash, ramda, etc.) are detected in test or automation scripts +- Violation handling: Pull requests adding external dependencies to automation scripts require architecture review and explicit justification +- Violation handling: Existing violations are tracked in technical debt backlog with migration plan to standard library equivalents +- Exception process: Submit exception request to tech lead with performance benchmarks or capability gap analysis +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration criteria +- Exception process: Review exceptions quarterly to assess if standard library improvements or refactoring can eliminate the need \ No newline at end of file diff --git a/docs/adr/7c5da194-79be-45e1-8dd2-fb82ce577b95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-python-automation-scripts.md b/docs/adr/7c5da194-79be-45e1-8dd2-fb82ce577b95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-python-automation-scripts.md new file mode 100644 index 00000000000..8ad00d9e67c --- /dev/null +++ b/docs/adr/7c5da194-79be-45e1-8dd2-fb82ce577b95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-python-automation-scripts.md @@ -0,0 +1,118 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Python Automation Scripts + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test specifications and automation scripts across the codebase demonstrate consistent patterns of importing core libraries (vitest, node:fs, node:path, argparse, json, sys, os) and performing data access operations using collection methods like find(), add(), and load(). +- The pattern emerges in three distinct contexts: TypeScript test files using vitest for parsing dumpsys output, Python scripts for GitHub PR labeling automation, and Python scripts for JSON validation, indicating a cross-language consistency in data access approaches. +- Data access patterns consistently involve in-memory collection operations (Set.add(), Array.find()) and file-based JSON loading (json.load(f)), suggesting a preference for simple, direct data manipulation over abstraction layers. +- The detection spans test frameworks (describe, it), standard library imports (node:fs, node:path, argparse, json, sys, os), and runtime libraries (vitest), indicating these are foundational dependencies for testing and automation workflows. + +## Problem Statement + +The codebase lacks explicit guidance on which core libraries and data access patterns should be used for test specifications and automation scripts, leading to potential inconsistency in how data is loaded, queried, and manipulated across different modules and languages. + +## Decision + +1. MUST: Python automation scripts MUST use standard library modules (json, sys, os, argparse) for file I/O, argument parsing, and JSON processing rather than external dependencies. + +## Policy Block + +- MUST Python automation scripts MUST use standard library modules (json, sys, os, argparse) for file I/O, argument parsing, and JSON processing rather than external dependencies. + +In scope: +- Test specification files (*.spec.ts, *.test.ts) +- Automation scripts in .github/scripts/ +- Validation and parsing utilities +- CI/CD pipeline scripts + +Out of scope: +- Production application code with complex query requirements +- Database access layers requiring ORM or query builders +- High-performance data processing pipelines +- Browser-based test runners (e.g., Playwright, Cypress) + +Exceptions: +- EXC-001: Performance profiling indicates native collection methods create bottlenecks in large dataset processing +- EXC-002: External API contracts require specific JSON schema validation libraries beyond standard json module capabilities + +## Rationale + +- The evidence shows consistent use of standard library modules across 3 files with 90.83% confidence, indicating an established pattern that minimizes external dependencies and reduces maintenance burden. +- Using native collection methods (find(), add()) and standard library JSON parsing provides predictable behavior, reduces bundle size, and eliminates version compatibility issues with third-party libraries. +- The pattern spans both TypeScript (vitest, node:fs, node:path) and Python (json, sys, os, argparse) contexts, demonstrating language-appropriate choices that align with ecosystem conventions. +- Direct data access patterns without abstraction layers are appropriate for the observed use cases (test parsing, label automation, JSON validation) where query complexity is low and transparency is valuable. + +## Consequences + +Positive: +- Reduced dependency footprint in test and automation scripts, minimizing security surface area and dependency update overhead +- Improved script portability and long-term maintainability by relying on stable standard library APIs rather than third-party package ecosystems +- Lower cognitive overhead for developers familiar with standard library APIs, reducing onboarding time for test and automation contributions +- Faster script execution and smaller bundle sizes due to elimination of unnecessary abstraction layers + +Negative: +- Limited query expressiveness for complex data access patterns, requiring manual predicate logic rather than declarative query syntax +- Potential code duplication if similar data access patterns are repeated across multiple scripts without shared utility functions +- Lack of type safety in Python json.load() operations without additional validation layers or schema enforcement +- Manual error handling required for file I/O and JSON parsing operations without framework-provided retry or validation mechanisms + +## Alternatives + +- Adopt lodash/underscore for collection operations and data manipulation in both TypeScript and Python scripts (rejected) + Rejected because: Evidence shows native methods (Array.find(), Set.add()) are sufficient for current use cases; adding lodash would increase bundle size and introduce unnecessary dependency without demonstrated performance or expressiveness benefits + When valid: Valid for scripts processing large datasets requiring complex transformations like groupBy, partition, or deep merging +- Use Pydantic or JSON Schema validators for structured JSON validation instead of raw json.load() (deferred) + Rejected because: Current validation scripts use simple duplicate detection and basic structure checks; schema validation libraries add complexity without clear evidence of validation requirements beyond basic parsing + When valid: Valid when external API contracts require strict schema enforcement or when validation error messages need to be user-facing +- Standardize on Jest instead of vitest for TypeScript test specifications (rejected) + Rejected because: Evidence explicitly shows vitest usage in test specifications; Jest would require migration effort and vitest provides faster execution with native ESM support + When valid: Valid for projects requiring Jest-specific ecosystem plugins or snapshot testing features not available in vitest + +## Risks + +- Scripts may grow complex enough that native collection methods become verbose and error-prone, leading to maintenance burden + Mitigation: Establish shared utility modules for common data access patterns; set complexity threshold (e.g., >3 nested loops) triggering refactor to query library + Owner: Engineering team +- Lack of schema validation in JSON loading may allow malformed data to propagate through automation pipelines, causing runtime failures + Mitigation: Add explicit validation checks after json.load() for critical fields; document expected JSON structure in script docstrings; consider schema validation for external data sources + Owner: DevOps and automation team +- Standard library file I/O patterns may not handle edge cases (encoding issues, large files, concurrent access) as robustly as specialized libraries + Mitigation: Document encoding assumptions (UTF-8) explicitly; add file size checks for large file handling; use file locking for concurrent access scenarios + Owner: Engineering team + +## Implementation Notes + +- Create shared utility modules for common patterns: parseJsonFile(), findInCollection(), addToSet() to reduce duplication while maintaining standard library usage +- Add ESLint/Pylint rules to flag imports of lodash, ramda, or other collection libraries in test and automation script directories +- Document standard library API patterns in developer guide with examples from existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) +- For new automation scripts, use existing scripts as templates to ensure consistency in import patterns and data access approaches + +## Continuation Context + + +Verify commands: +- grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l +- grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l +- grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l +- grep -r "\.find(\|.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +Accept when: +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts + +## Enforcement + +- Verified by: CI pipeline static analysis checking for prohibited third-party imports in test and automation script directories +- Verified by: Code review checklist item verifying standard library usage for new test specifications and automation scripts +- Verified by: Automated dependency audits flagging new dependencies in package.json or requirements.txt within scope directories +- Violation handling: CI build fails if prohibited imports (lodash, ramda, etc.) are detected in test or automation scripts +- Violation handling: Pull requests adding external dependencies to automation scripts require architecture review and explicit justification +- Violation handling: Existing violations are tracked in technical debt backlog with migration plan to standard library equivalents +- Exception process: Submit exception request to tech lead with performance benchmarks or capability gap analysis +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration criteria +- Exception process: Review exceptions quarterly to assess if standard library improvements or refactoring can eliminate the need \ No newline at end of file diff --git a/docs/adr/7f825e0c-d33b-43a0-ac74-3b7da9eefd92-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-activities-extending-componentactivity.md b/docs/adr/7f825e0c-d33b-43a0-ac74-3b7da9eefd92-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-activities-extending-componentactivity.md new file mode 100644 index 00000000000..59d9f821f57 --- /dev/null +++ b/docs/adr/7f825e0c-d33b-43a0-ac74-3b7da9eefd92-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-activities-extending-componentactivity.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Activities Extending Componentactivity + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. SHOULD: Activities extending ComponentActivity or AppCompatActivity SHOULD use @AndroidEntryPoint for lifecycle-aware injection + +## Policy Block + +- SHOULD Activities extending ComponentActivity or AppCompatActivity SHOULD use @AndroidEntryPoint for lifecycle-aware injection + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/7fe11545-7b45-4360-a8bc-2d5c37949407-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-application-class-use.md b/docs/adr/7fe11545-7b45-4360-a8bc-2d5c37949407-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-application-class-use.md new file mode 100644 index 00000000000..ded9a526ef9 --- /dev/null +++ b/docs/adr/7fe11545-7b45-4360-a8bc-2d5c37949407-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-application-class-use.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Application Class Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. MUST: The Application class MUST use @Inject for field or constructor injection of application-scoped dependencies + +## Policy Block + +- MUST The Application class MUST use @Inject for field or constructor injection of application-scoped dependencies + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/822904f8-d778-409d-ab3f-a2f2d3bfbac0-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-methods.md b/docs/adr/822904f8-d778-409d-ab3f-a2f2d3bfbac0-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-methods.md new file mode 100644 index 00000000000..4fcca8b5b66 --- /dev/null +++ b/docs/adr/822904f8-d778-409d-ab3f-a2f2d3bfbac0-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-methods.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Python Test Methods + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. MUST: Python test methods MUST follow the test_* naming convention + +## Policy Block + +- MUST Python test methods MUST follow the test_* naming convention + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/85dbd58a-e138-490a-ad09-20a2013a0794-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-fixtures-organized.md b/docs/adr/85dbd58a-e138-490a-ad09-20a2013a0794-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-fixtures-organized.md new file mode 100644 index 00000000000..f85f5459274 --- /dev/null +++ b/docs/adr/85dbd58a-e138-490a-ad09-20a2013a0794-adopt-unittest-and-vitest-as-standard-testing-frameworks-test-fixtures-organized.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Test Fixtures Organized + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. SHOULD: Test fixtures SHOULD be organized in dedicated fixtures/ directories relative to test files + +## Policy Block + +- SHOULD Test fixtures SHOULD be organized in dedicated fixtures/ directories relative to test files + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/874842c0-a39c-4d3a-b1a9-4349607256d3-use-json-builder-dsl-for-test-assertion-construction-serialization-tests-verify.md b/docs/adr/874842c0-a39c-4d3a-b1a9-4349607256d3-use-json-builder-dsl-for-test-assertion-construction-serialization-tests-verify.md new file mode 100644 index 00000000000..52d07e82f3f --- /dev/null +++ b/docs/adr/874842c0-a39c-4d3a-b1a9-4349607256d3-use-json-builder-dsl-for-test-assertion-construction-serialization-tests-verify.md @@ -0,0 +1,101 @@ +# Use JSON Builder DSL for Test Assertion Construction: Serialization Tests Verify + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests require verification that domain objects correctly encode to JSON with specific structure and type discriminators +- The codebase uses kotlinx.serialization for JSON encoding/decoding with custom serializers for versioned state objects +- Test assertions need to compare expected JSON structure against actual serializer output without string-based comparison fragility +- The buildJsonObject DSL with put operations provides type-safe construction of expected JSON structures for assertion matching + +## Problem Statement + +Test assertions for JSON serialization require a reliable method to construct expected JSON structures that can be compared against actual serializer output. String-based JSON comparison is fragile and difficult to maintain, while manual JsonObject construction is verbose and error-prone. A standardized approach is needed to build expected JSON structures in tests that is both readable and type-safe. + +## Decision + +1. SHOULD: Serialization tests SHOULD verify type discriminator fields are present in versioned state objects + +## Policy Block + +- SHOULD Serialization tests SHOULD verify type discriminator fields are present in versioned state objects + +## Rationale + +- The pattern appears in 2 test files with 91.70% confidence, both using buildJsonObject with put operations for JSON assertion construction +- WrappedAccountCryptographicStateSerializerTest demonstrates the pattern for versioned state objects (V1, V2) with type discriminators +- VaultSdkPolicyExtensionsTest shows the pattern applied to SDK policy conversion testing with empty list and multi-item list scenarios +- The kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put functions provide the DSL foundation for this testing approach + +## Consequences + +Positive: +- Type-safe JSON construction in tests reduces runtime errors from malformed JSON strings +- DSL syntax improves test readability by making JSON structure explicit and self-documenting +- Refactoring serialization logic becomes safer as tests clearly express expected structure +- IDE support for DSL provides autocomplete and type checking during test development + +Negative: +- Developers must learn kotlinx.serialization DSL syntax in addition to standard assertion libraries +- Verbose buildJsonObject blocks may increase test code size compared to raw JSON strings +- Pattern creates coupling to kotlinx.serialization library for test infrastructure +- Complex nested JSON structures may become difficult to read despite DSL benefits + +## Alternatives + +- Use raw JSON strings with Json.parseToJsonElement for expected values (rejected) + Rejected because: String-based JSON is fragile, lacks type safety, and requires manual escaping of special characters + When valid: Acceptable for simple one-off tests where JSON structure is trivial and unlikely to change +- Construct JsonObject instances directly using JsonObject constructor (rejected) + Rejected because: Direct constructor usage is verbose and less readable than DSL syntax, reducing test maintainability + When valid: Valid when buildJsonObject DSL is unavailable or when programmatic construction is required +- Use snapshot testing to capture serialized JSON output (deferred) + Rejected because: Not rejected but deferred; snapshot testing complements rather than replaces structural assertions + When valid: Useful for regression testing of large JSON structures where exact structure verification is needed + +## Risks + +- DSL syntax changes in kotlinx.serialization updates could break existing tests + Mitigation: Pin kotlinx.serialization version and review release notes before upgrades; maintain test suite coverage + Owner: engineering team +- Overuse of buildJsonObject for simple assertions may reduce test clarity + Mitigation: Establish guidelines for when DSL is appropriate versus simpler assertion methods; code review enforcement + Owner: engineering team +- New team members unfamiliar with kotlinx.serialization DSL may write inconsistent tests + Mitigation: Document pattern in testing guidelines; provide examples in test templates; conduct code review training + Owner: engineering team + +## Implementation Notes + +- Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern +- Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order +- For versioned state objects, always verify the type discriminator field first in the buildJsonObject block +- Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests + +## Continuation Context + + +Verify commands: +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l +- grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' +- ./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' + +Accept when: +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output + +## Enforcement + +- Verified by: Code review checklist requiring buildJsonObject usage in serialization tests +- Verified by: Static analysis or linting rules detecting raw JSON strings in test assertions +- Verified by: CI pipeline test execution validating serialization test coverage +- Violation handling: Code review feedback requesting refactoring to buildJsonObject DSL +- Violation handling: Pull request comments with examples of correct pattern usage +- Violation handling: Test failures flagged for investigation if serialization assertions use non-standard approaches +- Exception process: Document rationale in test comments when alternative assertion method is necessary +- Exception process: Obtain approval from tech lead for exceptions in complex or legacy test scenarios +- Exception process: Track exceptions in testing guidelines document with justification and review date \ No newline at end of file diff --git a/docs/adr/87712dbb-078d-457f-a0d9-2400b5d8b012-standardize-console-error-and-response-error-for-error-logging-in-libraries-libraries-provide-hooks.md b/docs/adr/87712dbb-078d-457f-a0d9-2400b5d8b012-standardize-console-error-and-response-error-for-error-logging-in-libraries-libraries-provide-hooks.md new file mode 100644 index 00000000000..31adcbe50cc --- /dev/null +++ b/docs/adr/87712dbb-078d-457f-a0d9-2400b5d8b012-standardize-console-error-and-response-error-for-error-logging-in-libraries-libraries-provide-hooks.md @@ -0,0 +1,117 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Libraries Provide Hooks + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Library modules in both TypeScript (android-device-server) and Kotlin (bitwarden network layer) implement error logging using platform-native error reporting mechanisms +- The TypeScript implementation uses console.error for tool errors and fatal errors in an MCP server context, while the Kotlin implementation uses Response.error with HTTP status codes and JSON-formatted error messages +- Both implementations integrate error logging within core library functionality, suggesting a cross-platform pattern for observable error handling in modular architectures +- The pattern appears in libraries that serve as integration points: an Android device MCP server and a network layer for API communication + +## Problem Statement + +Library modules require consistent, observable error logging mechanisms that integrate with their respective runtime environments (Node.js console for TypeScript, Retrofit Response for Kotlin) to enable debugging, monitoring, and error propagation without introducing external logging framework dependencies. + +## Decision + +1. MAY: Libraries MAY provide hooks or callbacks for consumers to integrate custom logging implementations while maintaining default platform-native error logging + +## Policy Block + +- MAY Libraries MAY provide hooks or callbacks for consumers to integrate custom logging implementations while maintaining default platform-native error logging + +In scope: +- TypeScript libraries running in Node.js environments with console API access +- Kotlin libraries using Retrofit for HTTP client functionality +- Library modules designed for reuse across multiple applications or services +- Error handling code paths within library boundaries + +Out of scope: +- Application-level logging infrastructure and aggregation systems +- Structured logging frameworks (Winston, Log4j, SLF4J) used by consuming applications +- Production monitoring and alerting systems external to library code +- Log persistence, rotation, or archival mechanisms + +Exceptions: +- EXC-001: Library is explicitly designed as a logging abstraction or wrapper (e.g., a logging facade library) +- EXC-002: Library operates in an environment without platform-native error logging (embedded systems, constrained runtimes) + +## Rationale + +- Platform-native error logging mechanisms (console.error, Response.error) are universally available in their respective runtime environments, eliminating external dependencies and reducing library footprint +- The pattern observed across TypeScript and Kotlin implementations demonstrates a cross-platform architectural principle: libraries should use runtime-provided error reporting rather than introducing framework coupling +- Using platform-native mechanisms enables library consumers to intercept, redirect, or enhance error logging through standard runtime hooks (console redirection, Retrofit interceptors) without modifying library code +- The evidence shows consistent integration of error logging with core library operations (tool execution, HTTP response construction), indicating error observability is treated as a first-class concern in library design + +## Consequences + +Positive: +- Reduced library dependency footprint by avoiding external logging framework dependencies +- Improved library portability across different application contexts and deployment environments +- Simplified library testing through standard console/response mocking mechanisms +- Enhanced consumer flexibility to integrate library error logging with application-specific monitoring infrastructure + +Negative: +- Limited structured logging capabilities compared to dedicated logging frameworks (no log levels, structured fields, or filtering) +- Potential inconsistency in error log format across different libraries and platforms +- Reduced observability features such as automatic context propagation, correlation IDs, or distributed tracing integration +- Console.error output may be difficult to parse or aggregate in production monitoring systems without additional tooling + +## Alternatives + +- Adopt a lightweight, cross-platform logging abstraction library (e.g., pino for TypeScript, SLF4J for Kotlin) as a standard dependency (rejected) + Rejected because: Introduces external dependency and version management complexity; conflicts with the observed pattern of using platform-native mechanisms; reduces library portability + When valid: When libraries require structured logging with log levels, filtering, and production-grade observability features that justify the dependency cost +- Implement custom logging abstraction within each library with pluggable backends (rejected) + Rejected because: Increases library code complexity and maintenance burden; duplicates logging abstraction logic across libraries; evidence shows preference for simple, direct error reporting + When valid: When building a library ecosystem with shared logging requirements and centralized logging infrastructure management +- Provide optional logging callback parameters for all error-prone operations (deferred) + Rejected because: Not observed in current evidence; would require API design changes across library interfaces + When valid: As an enhancement to enable custom error handling while maintaining platform-native defaults (see R-20-006) + +## Risks + +- Inconsistent error log formats across libraries make centralized monitoring and alerting difficult to implement + Mitigation: Establish error message format conventions (e.g., prefix patterns, JSON structure) documented in library development guidelines; provide examples of log parsing patterns for common monitoring tools + Owner: Engineering team, library maintainers +- Platform-native error logging may not provide sufficient detail for debugging complex library interactions in production + Mitigation: Ensure error messages include actionable context (operation name, input parameters, error codes); document error scenarios and troubleshooting steps in library documentation; consider optional verbose logging modes + Owner: Engineering team +- Console.error output in high-throughput scenarios may impact performance or overwhelm log aggregation systems + Mitigation: Implement error rate limiting or sampling for repetitive errors; document expected error logging volume in library performance characteristics; provide guidance on console redirection for production environments + Owner: Engineering team, SRE team + +## Implementation Notes + +- For TypeScript libraries, use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin network libraries using Retrofit, construct Response.error with appropriate HTTP status codes (e.g., HTTP_CODE_BAD_REQUEST) and JSON-formatted error messages using ResponseBody.Companion.toResponseBody +- Include sufficient context in error messages to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes +- Document expected error log output format and examples in library README to help consumers implement log parsing and monitoring + +## Continuation Context + + +Verify commands: +- grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" +- grep -r "Response\.error" --include="*.kt" src/ | head -20 +- grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l + +Accept when: +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + +## Enforcement + +- Verified by: Code review checklist verifying use of platform-native error logging mechanisms +- Verified by: Dependency analysis in CI pipeline flagging external logging framework dependencies in library modules +- Verified by: Grep-based verification commands checking for console.error and Response.error patterns in library code +- Violation handling: Code review feedback requesting removal of external logging framework dependencies and migration to platform-native mechanisms +- Violation handling: CI pipeline warnings when external logging dependencies are detected in library package manifests +- Violation handling: Architecture review required for libraries that cannot use platform-native error logging due to runtime constraints +- Exception process: Submit exception request documenting runtime environment constraints or logging requirements that cannot be met with platform-native mechanisms +- Exception process: Technical lead or architecture review approval required for exception +- Exception process: Document approved exceptions in library README with justification and alternative error reporting mechanism details \ No newline at end of file diff --git a/docs/adr/8b2d3bbd-e62e-41da-846f-2a7b570dfef8-adopt-async-handler-pattern-for-tool-operations-tool-modules-separate.md b/docs/adr/8b2d3bbd-e62e-41da-846f-2a7b570dfef8-adopt-async-handler-pattern-for-tool-operations-tool-modules-separate.md new file mode 100644 index 00000000000..6e965f0ac89 --- /dev/null +++ b/docs/adr/8b2d3bbd-e62e-41da-846f-2a7b570dfef8-adopt-async-handler-pattern-for-tool-operations-tool-modules-separate.md @@ -0,0 +1,120 @@ +# Adopt Async Handler Pattern for Tool Operations: Tool Modules Separate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the android-device-server MCP service. + +## Context + +- The android-device-server MCP service implements multiple tool operations (capture, tap-at, find-element-pipeline) that interact with external Android Debug Bridge (adb) processes and file system operations +- Tool operations require coordination of asynchronous I/O including process execution, file reads/writes, and validation steps that cannot block the event loop +- Each tool exports a handler function that serves as the primary entry point for tool invocation, establishing a consistent interface pattern across the codebase +- The codebase uses Zod for input validation schemas and node:path/node:fs for file system operations, requiring async coordination between validation and execution phases + +## Problem Statement + +Tool operations in the android-device-server require a consistent concurrency model that coordinates asynchronous validation, external process execution, and file system operations without blocking the Node.js event loop, while maintaining a uniform interface pattern across all tool implementations. + +## Decision + +1. SHOULD: Tool modules SHOULD separate validation schemas from handler implementation for clarity and reusability + +## Policy Block + +- SHOULD Tool modules SHOULD separate validation schemas from handler implementation for clarity and reusability + +In scope: +- All tool implementations in the android-device-server/src/tools directory +- Handler functions that coordinate adb process execution +- Operations involving file system reads/writes via node:fs +- Tool entry points exported for MCP service consumption + +Out of scope: +- Utility functions that do not serve as tool entry points +- Synchronous helper functions for data transformation +- Type definitions and interface declarations +- Test harness and mock implementations + +Exceptions: +- EXC-001: Pure computational functions that perform synchronous transformations without I/O + +## Rationale + +- The evidence shows consistent use of async handler functions (capture, tapAt, findElementWithObstruction) across 3 tool implementations, indicating an established pattern for coordinating asynchronous operations +- All detected tools import adb utilities and validation modules, requiring async coordination between validation, process execution, and result handling +- The handler pattern provides a uniform interface for tool invocation while encapsulating the complexity of async I/O coordination with external processes and file systems +- Using async/await patterns prevents event loop blocking and enables proper error propagation in the Node.js runtime environment + +## Consequences + +Positive: +- Consistent interface pattern across all tool implementations improves code maintainability and developer onboarding +- Non-blocking async operations ensure the MCP service remains responsive during long-running adb operations +- Separation of validation and execution phases enables early input rejection before expensive I/O operations +- Async/await syntax provides clear error handling and control flow compared to callback-based patterns + +Negative: +- Async handler pattern adds complexity compared to synchronous implementations for simple operations +- Requires developers to understand Promise semantics and async/await error handling +- Potential for unhandled promise rejections if error handling is not properly implemented +- Debugging async call stacks can be more challenging than synchronous execution flows + +## Alternatives + +- Synchronous handler functions with blocking I/O operations (rejected) + Rejected because: Blocking I/O would freeze the Node.js event loop during adb process execution and file operations, making the service unresponsive to concurrent requests + When valid: Only appropriate for pure computational functions without I/O dependencies +- Callback-based asynchronous pattern using Node.js callback conventions (rejected) + Rejected because: Callback patterns lead to nested callback hell and more complex error handling compared to async/await syntax available in modern Node.js + When valid: Legacy codebases or when targeting very old Node.js versions without async/await support +- Event emitter pattern for tool operations (rejected) + Rejected because: Event emitters add unnecessary complexity for request-response tool operations that have clear start and end points + When valid: Appropriate for streaming operations or long-running processes with multiple intermediate events + +## Risks + +- Unhandled promise rejections in handler functions could crash the Node.js process or leave operations in inconsistent states + Mitigation: Implement comprehensive try-catch blocks in all async handlers and configure Node.js to log unhandled rejections. Add integration tests that verify error handling paths. + Owner: Engineering team +- Long-running adb operations could accumulate pending promises and exhaust memory if not properly managed + Mitigation: Implement timeouts for all adb operations and add monitoring for pending promise counts. Consider implementing operation queuing with concurrency limits. + Owner: Engineering team +- Inconsistent error handling patterns across handlers could lead to unpredictable failure modes + Mitigation: Establish standard error handling patterns and document them. Create shared error handling utilities that all handlers can use. + Owner: Engineering team + +## Implementation Notes + +- All new tool implementations should follow the pattern: export an async function that accepts validated parameters and returns a Promise of the operation result +- Use Zod schemas defined at module level for input validation, and validate before entering the async handler logic +- Import adb utilities and file system operations from their respective modules (../adb/adb.js, node:fs, node:path) and await their results +- Ensure all async handlers have proper error handling with try-catch blocks and meaningful error messages that include context about the failed operation + +## Continuation Context + + +Verify commands: +- grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + +## Enforcement + +- Verified by: Code review checklist requiring async handler pattern for new tools +- Verified by: ESLint rules detecting synchronous I/O operations in tool handlers +- Verified by: Integration tests verifying non-blocking behavior under concurrent load +- Violation handling: Code review rejection for synchronous I/O in handler functions +- Violation handling: CI pipeline failure on ESLint violations for blocking operations +- Violation handling: Automated comments on PRs identifying missing async/await patterns +- Exception process: Document exception rationale in ADR amendment or inline code comments +- Exception process: Obtain tech lead approval for synchronous operations in tool handlers +- Exception process: Add exception to ESLint configuration with justification comment \ No newline at end of file diff --git a/docs/adr/8bf8bb07-c7a7-4dc6-ae85-95c75ba9efd9-adopt-zod-schema-validation-for-tool-input-parameters-optional-parameters-declare.md b/docs/adr/8bf8bb07-c7a7-4dc6-ae85-95c75ba9efd9-adopt-zod-schema-validation-for-tool-input-parameters-optional-parameters-declare.md new file mode 100644 index 00000000000..d446349bd7e --- /dev/null +++ b/docs/adr/8bf8bb07-c7a7-4dc6-ae85-95c75ba9efd9-adopt-zod-schema-validation-for-tool-input-parameters-optional-parameters-declare.md @@ -0,0 +1,116 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Optional Parameters Declare + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the Android Device Server MCP that accept external input parameters. + +## Context + +- The Android Device Server MCP exposes tool handlers that accept external input from clients, requiring validation to prevent invalid operations and runtime errors +- Tool parameters include coordinates, timing values, and boolean flags that must conform to specific constraints (non-negative integers, minimum values, type safety) +- The codebase imports 'zod' as a core dependency and '../utils/validation.js' across multiple tool implementations, indicating a standardized validation approach +- Two tool handlers (capture.ts and tap-at.ts) demonstrate consistent schema definition patterns using z.object() with typed field validators + +## Problem Statement + +Tool handlers in the Android Device Server MCP must validate external input parameters to ensure type safety, enforce domain constraints (e.g., non-negative coordinates, valid timing ranges), and prevent invalid ADB commands from being executed, but without a standardized validation approach, each tool would implement ad-hoc validation logic leading to inconsistency and maintenance burden. + +## Decision + +1. SHOULD: Optional parameters SHOULD declare default values using .optional().default() to simplify client usage + +## Policy Block + +- SHOULD Optional parameters SHOULD declare default values using .optional().default() to simplify client usage + +In scope: +- All tool handler implementations in src/tools/ that accept external parameters +- Input validation for ADB command parameters (coordinates, timing, flags) +- Public API contracts exposed through MCP tool interfaces + +Out of scope: +- Internal utility functions that do not accept external input +- ADB command output parsing and response formatting +- Device discovery and connection management logic + +## Rationale + +- The evidence shows consistent use of Zod schemas across capture.ts and tap-at.ts with identical import patterns ('zod', '../utils/validation.js'), indicating an established validation standard +- Schema definitions enforce domain-specific constraints (non-negative coordinates, minimum timing values) that prevent invalid ADB commands and improve system reliability +- Centralized validation through Zod provides type inference, runtime validation, and clear error messages, reducing boilerplate and improving developer experience +- The pattern appears in the security.input_validation facet with 91.20% confidence across 2 files, demonstrating measurable adoption + +## Consequences + +Positive: +- Type-safe input validation with automatic TypeScript type inference from schemas +- Consistent validation error messages and handling across all tool implementations +- Reduced boilerplate code compared to manual parameter checking and validation +- Clear API contracts that are self-documenting through schema definitions + +Negative: +- Additional runtime overhead for schema validation on every tool invocation +- Dependency on the Zod library increases bundle size and introduces external maintenance risk +- Developers must learn Zod API and schema composition patterns +- Schema definitions add verbosity to tool handler implementations + +## Alternatives + +- Manual parameter validation using TypeScript type guards and conditional checks (rejected) + Rejected because: Leads to inconsistent validation logic, verbose boilerplate, and no runtime type safety guarantees + When valid: For simple internal functions with minimal validation requirements +- Use JSON Schema with ajv validator for runtime validation (rejected) + Rejected because: Requires separate type definitions and schema definitions, losing TypeScript type inference benefits + When valid: When interoperating with systems that already use JSON Schema standards +- Use io-ts for functional programming style validation (rejected) + Rejected because: Steeper learning curve and more verbose syntax compared to Zod's developer-friendly API + When valid: In codebases with strong functional programming conventions using fp-ts + +## Risks + +- Zod library vulnerabilities or breaking changes in future versions could impact all tool handlers + Mitigation: Pin Zod version in package.json, monitor security advisories, and maintain comprehensive test coverage for validation logic + Owner: engineering team +- Complex nested schemas may introduce performance bottlenecks for high-frequency tool invocations + Mitigation: Profile validation performance, cache parsed schemas, and consider lazy validation for optional deep structures + Owner: engineering team +- Inconsistent schema patterns across tools if validation utilities are not properly documented + Mitigation: Document standard validation patterns in ../utils/validation.js, provide schema templates, and enforce through code review + Owner: engineering team + +## Implementation Notes + +- Import Zod and validation utilities at the top of each tool handler: import { z } from 'zod' and import validation utilities from '../utils/validation.js' +- Define the input schema as a const using z.object() with appropriate field validators before the handler function +- Use .int().nonnegative() for coordinate parameters, .min(0) for timing parameters, and .optional().default() for optional flags +- Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages +- Export the inferred TypeScript type using z.infer for use in function signatures and documentation + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "../utils/validation" .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool handlers in src/tools/ that accept external parameters import 'zod' and define validation schemas +- Grep commands show consistent usage of z.object() schema definitions across tool implementations +- Validation utility imports from '../utils/validation.js' are present in all relevant tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for new tool handlers +- Verified by: Automated grep-based checks in CI pipeline verifying presence of validation imports +- Verified by: TypeScript compilation ensuring type safety through schema inference +- Violation handling: Pull requests adding tool handlers without Zod validation are rejected during code review +- Violation handling: CI pipeline fails if tool files lack required validation imports +- Violation handling: Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation +- Exception process: Exceptions require written justification documenting why Zod validation is inappropriate for the specific use case +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in code comments with reference to approval decision \ No newline at end of file diff --git a/docs/adr/8c033a44-0889-415a-8770-e35d0d4c03fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-use-mutablestateflow.md b/docs/adr/8c033a44-0889-415a-8770-e35d0d4c03fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-use-mutablestateflow.md new file mode 100644 index 00000000000..82e67cbf059 --- /dev/null +++ b/docs/adr/8c033a44-0889-415a-8770-e35d0d4c03fb-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-use-mutablestateflow.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Use Mutablestateflow + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. MUST: ViewModels MUST use MutableStateFlow to hold UI state and expose it as immutable StateFlow to UI consumers + +## Policy Block + +- MUST ViewModels MUST use MutableStateFlow to hold UI state and expose it as immutable StateFlow to UI consumers + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/8d59b907-3996-4bdc-b0e6-38744356cc8f-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-json-configuration-files.md b/docs/adr/8d59b907-3996-4bdc-b0e6-38744356cc8f-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-json-configuration-files.md new file mode 100644 index 00000000000..8a2c685cd70 --- /dev/null +++ b/docs/adr/8d59b907-3996-4bdc-b0e6-38744356cc8f-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-json-configuration-files.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Json Configuration Files + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. MUST: JSON configuration files MUST be validated using json.load() with exception handling to catch malformed data before processing + +## Policy Block + +- MUST JSON configuration files MUST be validated using json.load() with exception handling to catch malformed data before processing + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/9b1cd432-f6b2-4d64-949d-1ed6f8997b22-standardize-kotlinx-serialization-json-testing-with-type-discriminators-test-classes-follow.md b/docs/adr/9b1cd432-f6b2-4d64-949d-1ed6f8997b22-standardize-kotlinx-serialization-json-testing-with-type-discriminators-test-classes-follow.md new file mode 100644 index 00000000000..01c09055e95 --- /dev/null +++ b/docs/adr/9b1cd432-f6b2-4d64-949d-1ed6f8997b22-standardize-kotlinx-serialization-json-testing-with-type-discriminators-test-classes-follow.md @@ -0,0 +1,116 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Test Classes Follow + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests validate JSON encoding/decoding behavior at service boundaries where data crosses module or API boundaries +- The codebase uses kotlinx.serialization for JSON serialization with custom serializers for domain models like WrappedAccountCryptographicState +- Type discriminators (e.g., 'v1', 'v2') enable versioned serialization formats to support backward compatibility and schema evolution +- Tests use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings +- The pattern appears in cryptographic state serialization and policy view conversion, indicating cross-cutting serialization concerns + +## Problem Statement + +Service boundaries require reliable serialization contracts that can evolve over time without breaking existing clients. Without standardized testing of JSON serialization including type discriminators and property mappings, schema changes may introduce silent data corruption or deserialization failures at runtime. + +## Decision + +1. SHOULD: Test classes SHOULD follow naming convention Test for serializers and extension functions + +## Policy Block + +- SHOULD Test classes SHOULD follow naming convention Test for serializers and extension functions + +In scope: +- Custom kotlinx.serialization serializers for domain models +- Extension functions converting between domain models and SDK types +- JSON encoding/decoding at service and module boundaries +- Versioned serialization formats using type discriminators + +Out of scope: +- Internal data transformations that do not cross serialization boundaries +- Third-party library serializers without custom logic +- Binary serialization formats +- Database entity mappings + +## Rationale + +- The evidence shows consistent use of kotlinx.serialization.json.buildJsonObject and assertEquals patterns across serialization tests, indicating an established testing approach +- Type discriminators ('v1', 'v2') in WrappedAccountCryptographicState tests demonstrate versioning requirements at cryptographic state boundaries +- Tests for toSdkPolicyViews extension function show validation of conversion logic between network models and SDK policy views +- The pattern appears in both data layer (cryptographic state) and vault repository (policy conversion), suggesting cross-cutting serialization concerns requiring standardized testing + +## Consequences + +Positive: +- Serialization contract changes are caught at test time rather than runtime, preventing data corruption +- Type discriminator validation ensures versioned schemas maintain backward compatibility +- Standardized test structure improves maintainability and makes serialization behavior explicit +- Extension function tests verify boundary conversions handle edge cases like empty lists + +Negative: +- Additional test code increases maintenance burden when serialization formats change +- Exact JSON structure assertions are brittle and may require updates for cosmetic changes +- Test duplication across similar serializers may occur without shared test utilities +- Mock factory functions add indirection that may obscure actual test data + +## Alternatives + +- Use property-based testing to verify serialization round-trips without asserting exact JSON structure (rejected) + Rejected because: Does not validate exact JSON contract including field names and discriminator values required for external API compatibility + When valid: Internal serialization where only round-trip fidelity matters, not exact wire format +- Generate serialization tests automatically from schema definitions (deferred) + Rejected because: Requires additional tooling and schema-first development approach not currently in place + When valid: When adopting schema-first API design with OpenAPI or JSON Schema definitions +- Rely on integration tests to catch serialization issues (rejected) + Rejected because: Integration tests are slower, less isolated, and provide poor feedback for serialization contract violations + When valid: Never as sole verification; integration tests complement but do not replace unit-level serialization tests + +## Risks + +- Brittle tests that break on benign JSON formatting changes (e.g., property order) + Mitigation: Use JSON comparison that ignores property order; consider semantic equality checks for non-critical formatting + Owner: engineering team +- Test coverage gaps for deserialization paths and error handling + Mitigation: Extend testing standard to include deserialization tests and malformed input handling + Owner: engineering team +- Type discriminator values may conflict across different serializers + Mitigation: Establish discriminator naming conventions and maintain registry of used discriminator values + Owner: architecture team + +## Implementation Notes + +- Create test classes in src/test/kotlin mirroring the package structure of serializers under test +- Use @Test annotation and assertEquals with buildJsonObject for exact JSON structure validation +- For versioned schemas, create separate test methods for each version verifying the type discriminator field +- When testing extension functions like toSdkPolicyViews, include edge cases such as empty lists and multi-item collections +- Consider extracting mock factory functions (e.g., createMockPolicy) to shared test utilities for reuse across test classes + +## Continuation Context + + +Verify commands: +- grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l +- find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +Accept when: +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + +## Enforcement + +- Verified by: Code review checklist requiring serialization tests for new serializers +- Verified by: CI pipeline test coverage reporting for serialization packages +- Verified by: Static analysis detecting serializers without corresponding test classes +- Violation handling: Pull requests adding serializers without tests are blocked in code review +- Violation handling: Coverage reports flag untested serialization code for remediation +- Violation handling: Architecture review required for serializers lacking discriminator validation +- Exception process: Exceptions require architecture team approval with documented justification +- Exception process: Temporary exceptions must include remediation plan and timeline +- Exception process: Exception requests must demonstrate why alternative testing approach provides equivalent contract validation \ No newline at end of file diff --git a/docs/adr/9bfdca65-6800-424e-96c4-a54a6ae4d05d-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-import.md b/docs/adr/9bfdca65-6800-424e-96c4-a54a6ae4d05d-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-import.md new file mode 100644 index 00000000000..4a21a6126d4 --- /dev/null +++ b/docs/adr/9bfdca65-6800-424e-96c4-a54a6ae4d05d-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-import.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Tool Handlers Import + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. SHOULD: Tool handlers SHOULD import core dependencies (zod, node:path, node:fs) and domain modules (../adb/adb.js, ../geometry/*) at the module level + +## Policy Block + +- SHOULD Tool handlers SHOULD import core dependencies (zod, node:path, node:fs) and domain modules (../adb/adb.js, ../geometry/*) at the module level + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/9c42ab5a-68cb-49ad-862a-c6599f730ae4-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-execution-errors.md b/docs/adr/9c42ab5a-68cb-49ad-862a-c6599f730ae4-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-execution-errors.md new file mode 100644 index 00000000000..6b5c894eee9 --- /dev/null +++ b/docs/adr/9c42ab5a-68cb-49ad-862a-c6599f730ae4-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-tool-execution-errors.md @@ -0,0 +1,114 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Tool Execution Errors + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements an MCP (Model Context Protocol) server using @modelcontextprotocol/sdk/server/index.js and stdio.js for communication +- Error conditions arise from both tool execution failures and fatal server-level errors requiring distinct logging contexts +- The server manages multiple tools accessed via a find pattern (tools.find(t => t.name === name)) requiring tool-scoped error identification +- Console-based logging provides immediate visibility in stdio-based server environments without external logging infrastructure dependencies +- The realtime boundary pattern (new Server with capabilities) necessitates synchronous error reporting for operational visibility + +## Problem Statement + +MCP servers operating over stdio require immediate, context-aware error logging that distinguishes between tool-level failures and fatal server errors while maintaining compatibility with the stdio transport layer and enabling operators to diagnose issues without external logging infrastructure. + +## Decision + +1. MUST: Tool execution errors MUST be logged using console.error with tool name context in the format 'Tool error ({name}): {message}' + +## Policy Block + +- MUST Tool execution errors MUST be logged using console.error with tool name context in the format 'Tool error ({name}): {message}' + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within the server capabilities boundary +- Fatal error conditions that terminate server operation +- Stdio-based transport layer error reporting + +Out of scope: +- Application-level logging within tool implementations +- Structured logging to external aggregation systems +- Client-side error handling and logging +- Non-error informational or debug logging + +## Rationale + +- The evidence shows explicit console.error usage for both tool-scoped errors (with name interpolation) and fatal errors, establishing a consistent pattern for synchronous error visibility +- The stdio transport layer used by @modelcontextprotocol/sdk/server/stdio.js requires console-based logging as the primary mechanism for operator visibility without interfering with protocol messages +- The tools.find pattern for tool resolution creates a natural boundary for tool-scoped error context, enabling precise error attribution +- The realtime server boundary (new Server with capabilities) necessitates immediate error reporting to maintain operational visibility during concurrent tool execution + +## Consequences + +Positive: +- Immediate error visibility in stdio-based environments without external dependencies +- Clear distinction between tool-level and server-level failures through consistent prefixing +- Simplified debugging through tool name context in error messages +- Zero-latency error reporting suitable for fatal error scenarios + +Negative: +- Console-based logging lacks structured metadata for automated analysis or aggregation +- No built-in error correlation across multiple tool invocations or server instances +- Limited filtering and search capabilities compared to structured logging systems +- Potential stderr pollution in environments with high error rates + +## Alternatives + +- Adopt structured logging library (e.g., winston, pino) with JSON output (rejected) + Rejected because: Adds external dependency and complexity for stdio-based MCP servers where console.error provides sufficient immediate visibility; structured logging better suited for long-running services with aggregation infrastructure + When valid: When MCP server operates in containerized environment with log aggregation pipeline or requires correlation across distributed tool executions +- Implement custom error event emitter with pluggable handlers (rejected) + Rejected because: Introduces abstraction overhead and delayed error reporting incompatible with fatal error scenarios requiring immediate visibility before process termination + When valid: When multiple error handling strategies must coexist or when error handling requires asynchronous processing +- Use MCP protocol error responses exclusively without console logging (rejected) + Rejected because: Protocol-level error responses do not provide operator visibility for fatal server errors or debugging during development; console logging serves distinct operational monitoring purpose + When valid: When all error handling occurs at client level and server-side operational monitoring is handled through external process supervision + +## Risks + +- Console error output may interfere with MCP protocol messages on stderr if not properly separated by transport layer + Mitigation: Verify @modelcontextprotocol/sdk/server/stdio.js properly isolates protocol messages from stderr; implement integration tests validating protocol integrity with error logging + Owner: MCP server engineering team +- Lack of structured error metadata limits automated error analysis and alerting capabilities + Mitigation: Document error message formats for parsing; consider hybrid approach with optional structured logging for production deployments while maintaining console.error baseline + Owner: Observability team +- Tool name context in error messages depends on correct name parameter propagation through tool resolution + Mitigation: Implement validation ensuring tool name is captured before execution; add fallback error logging for tool resolution failures + Owner: MCP server engineering team + +## Implementation Notes + +- Wrap all tool execution in try-catch blocks that call console.error with 'Tool error ({name}):' prefix before propagating or handling errors +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) before process exit +- Ensure tool name is captured from tools.find(t => t.name === name) result before execution to guarantee availability in error context +- Consider adding error codes or categories as structured prefixes within console.error messages to enable basic parsing without full structured logging + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ + +Accept when: +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + +## Enforcement + +- Verified by: Code review checking for console.error usage in error handling paths +- Verified by: Integration tests validating error log output format and content +- Verified by: Grep-based verification commands in CI pipeline +- Violation handling: Code review rejection for error handling without console.error logging +- Violation handling: CI pipeline warnings for missing tool name context in error logs +- Violation handling: Post-incident review when operational errors lack sufficient logging context +- Exception process: Document rationale for alternative logging approach in code comments +- Exception process: Obtain approval from observability team for structured logging adoption +- Exception process: Update ADR with amendment describing exception scope and justification \ No newline at end of file diff --git a/docs/adr/9c5ac160-2570-425b-91d6-cc6e790ed980-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-tests-organize.md b/docs/adr/9c5ac160-2570-425b-91d6-cc6e790ed980-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-tests-organize.md new file mode 100644 index 00000000000..7a4d541a73c --- /dev/null +++ b/docs/adr/9c5ac160-2570-425b-91d6-cc6e790ed980-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-typescript-tests-organize.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Typescript Tests Organize + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. SHOULD: TypeScript tests SHOULD organize related test cases using nested describe blocks to provide hierarchical test structure + +## Policy Block + +- SHOULD TypeScript tests SHOULD organize related test cases using nested describe blocks to provide hierarchical test structure + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/9c9dd63b-7128-418f-a8e3-558cd55fddac-standardize-kotlinx-serialization-json-testing-with-type-discriminators-extension-functions-that.md b/docs/adr/9c9dd63b-7128-418f-a8e3-558cd55fddac-standardize-kotlinx-serialization-json-testing-with-type-discriminators-extension-functions-that.md new file mode 100644 index 00000000000..345c8a9b4c0 --- /dev/null +++ b/docs/adr/9c9dd63b-7128-418f-a8e3-558cd55fddac-standardize-kotlinx-serialization-json-testing-with-type-discriminators-extension-functions-that.md @@ -0,0 +1,116 @@ +# Standardize Kotlinx Serialization JSON Testing with Type Discriminators: Extension Functions That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests validate JSON encoding/decoding behavior at service boundaries where data crosses module or API boundaries +- The codebase uses kotlinx.serialization for JSON serialization with custom serializers for domain models like WrappedAccountCryptographicState +- Type discriminators (e.g., 'v1', 'v2') enable versioned serialization formats to support backward compatibility and schema evolution +- Tests use buildJsonObject and assertEquals to verify exact JSON structure including discriminator fields and property mappings +- The pattern appears in cryptographic state serialization and policy view conversion, indicating cross-cutting serialization concerns + +## Problem Statement + +Service boundaries require reliable serialization contracts that can evolve over time without breaking existing clients. Without standardized testing of JSON serialization including type discriminators and property mappings, schema changes may introduce silent data corruption or deserialization failures at runtime. + +## Decision + +1. SHOULD: Extension functions that convert domain models to SDK types (e.g., toSdkPolicyViews) SHOULD have tests verifying empty input and multi-item conversion + +## Policy Block + +- SHOULD Extension functions that convert domain models to SDK types (e.g., toSdkPolicyViews) SHOULD have tests verifying empty input and multi-item conversion + +In scope: +- Custom kotlinx.serialization serializers for domain models +- Extension functions converting between domain models and SDK types +- JSON encoding/decoding at service and module boundaries +- Versioned serialization formats using type discriminators + +Out of scope: +- Internal data transformations that do not cross serialization boundaries +- Third-party library serializers without custom logic +- Binary serialization formats +- Database entity mappings + +## Rationale + +- The evidence shows consistent use of kotlinx.serialization.json.buildJsonObject and assertEquals patterns across serialization tests, indicating an established testing approach +- Type discriminators ('v1', 'v2') in WrappedAccountCryptographicState tests demonstrate versioning requirements at cryptographic state boundaries +- Tests for toSdkPolicyViews extension function show validation of conversion logic between network models and SDK policy views +- The pattern appears in both data layer (cryptographic state) and vault repository (policy conversion), suggesting cross-cutting serialization concerns requiring standardized testing + +## Consequences + +Positive: +- Serialization contract changes are caught at test time rather than runtime, preventing data corruption +- Type discriminator validation ensures versioned schemas maintain backward compatibility +- Standardized test structure improves maintainability and makes serialization behavior explicit +- Extension function tests verify boundary conversions handle edge cases like empty lists + +Negative: +- Additional test code increases maintenance burden when serialization formats change +- Exact JSON structure assertions are brittle and may require updates for cosmetic changes +- Test duplication across similar serializers may occur without shared test utilities +- Mock factory functions add indirection that may obscure actual test data + +## Alternatives + +- Use property-based testing to verify serialization round-trips without asserting exact JSON structure (rejected) + Rejected because: Does not validate exact JSON contract including field names and discriminator values required for external API compatibility + When valid: Internal serialization where only round-trip fidelity matters, not exact wire format +- Generate serialization tests automatically from schema definitions (deferred) + Rejected because: Requires additional tooling and schema-first development approach not currently in place + When valid: When adopting schema-first API design with OpenAPI or JSON Schema definitions +- Rely on integration tests to catch serialization issues (rejected) + Rejected because: Integration tests are slower, less isolated, and provide poor feedback for serialization contract violations + When valid: Never as sole verification; integration tests complement but do not replace unit-level serialization tests + +## Risks + +- Brittle tests that break on benign JSON formatting changes (e.g., property order) + Mitigation: Use JSON comparison that ignores property order; consider semantic equality checks for non-critical formatting + Owner: engineering team +- Test coverage gaps for deserialization paths and error handling + Mitigation: Extend testing standard to include deserialization tests and malformed input handling + Owner: engineering team +- Type discriminator values may conflict across different serializers + Mitigation: Establish discriminator naming conventions and maintain registry of used discriminator values + Owner: architecture team + +## Implementation Notes + +- Create test classes in src/test/kotlin mirroring the package structure of serializers under test +- Use @Test annotation and assertEquals with buildJsonObject for exact JSON structure validation +- For versioned schemas, create separate test methods for each version verifying the type discriminator field +- When testing extension functions like toSdkPolicyViews, include edge cases such as empty lists and multi-item collections +- Consider extracting mock factory functions (e.g., createMockPolicy) to shared test utilities for reuse across test classes + +## Continuation Context + + +Verify commands: +- grep -r '@Test' app/src/test/kotlin --include='*SerializerTest.kt' | wc -l +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | grep 'assertEquals' | wc -l +- find app/src/test/kotlin -name '*SerializerTest.kt' -o -name '*ExtensionsTest.kt' | xargs grep -l 'kotlinx.serialization' + +Accept when: +- All custom serializers have corresponding test classes with @Test methods +- Serialization tests use buildJsonObject and assertEquals to verify JSON structure +- Tests for versioned schemas validate type discriminator field values +- Extension function tests cover empty input and multi-item conversion cases + +## Enforcement + +- Verified by: Code review checklist requiring serialization tests for new serializers +- Verified by: CI pipeline test coverage reporting for serialization packages +- Verified by: Static analysis detecting serializers without corresponding test classes +- Violation handling: Pull requests adding serializers without tests are blocked in code review +- Violation handling: Coverage reports flag untested serialization code for remediation +- Violation handling: Architecture review required for serializers lacking discriminator validation +- Exception process: Exceptions require architecture team approval with documented justification +- Exception process: Temporary exceptions must include remediation plan and timeline +- Exception process: Exception requests must demonstrate why alternative testing approach provides equivalent contract validation \ No newline at end of file diff --git a/docs/adr/9d193d2c-ca56-4e12-9dc7-0666fbb5267a-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composable-functions-integrate.md b/docs/adr/9d193d2c-ca56-4e12-9dc7-0666fbb5267a-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composable-functions-integrate.md new file mode 100644 index 00000000000..c699e9b34db --- /dev/null +++ b/docs/adr/9d193d2c-ca56-4e12-9dc7-0666fbb5267a-adopt-jetpack-compose-as-standard-ui-framework-for-android-screens-composable-functions-integrate.md @@ -0,0 +1,118 @@ +# Adopt Jetpack Compose as Standard UI Framework for Android Screens: Composable Functions Integrate + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains multiple UI screens in the authentication feature module that require declarative UI composition with state management +- Android UI development has shifted from imperative XML-based layouts to declarative composition patterns for improved maintainability and testability +- The authentication flow includes complex screens (SetupUnlockScreen, ExpiredRegistrationLinkScreen, CompleteRegistrationHandler) that benefit from composable function decomposition +- The project structure indicates a Kotlin-first Android application requiring modern UI framework capabilities for layout composition and event handling + +## Problem Statement + +Android UI screens require a consistent framework for declarative composition, state management, and layout construction that supports modular screen development, type-safe component hierarchies, and integration with ViewModel architecture patterns across authentication and feature modules. + +## Decision + +1. MUST: Composable functions MUST integrate with androidx.compose.runtime utilities (remember, Composable annotation) for state management + +## Policy Block + +- MUST Composable functions MUST integrate with androidx.compose.runtime utilities (remember, Composable annotation) for state management + +In scope: +- All UI screens in app/src/main/kotlin/com/x8bit/bitwarden/ui/ module hierarchy +- Authentication feature screens and handlers +- New screen implementations across all feature modules +- Layout composition and state management code + +Out of scope: +- Legacy XML-based layouts if present for backward compatibility +- Non-UI Kotlin code (domain logic, data layer, repositories) +- Platform-specific native views that cannot be composed +- Third-party library UI components that do not support Compose integration + +Exceptions: +- EXC-001: Integrating third-party Android Views that do not provide Compose wrappers +- EXC-002: Performance-critical rendering scenarios where Compose overhead is measured and unacceptable + +## Rationale + +- Pattern detection identified 3 files with 92.50% confidence using @Composable annotation and androidx.compose.* APIs, demonstrating established adoption in authentication screens +- Jetpack Compose provides type-safe, declarative UI composition that reduces boilerplate and improves testability compared to imperative View-based approaches +- The detected usage pattern shows consistent integration with ViewModel architecture (CompleteRegistrationViewModel) and action handling, indicating architectural alignment +- Compose's foundation and runtime libraries provide comprehensive layout, state management, and lifecycle integration capabilities required for modern Android UI development + +## Consequences + +Positive: +- Declarative UI composition reduces boilerplate code and improves screen implementation maintainability +- Type-safe composable functions enable compile-time verification of UI component hierarchies and parameter contracts +- Integration with androidx.compose.runtime provides built-in state management and recomposition optimization +- Modular composable functions improve testability through isolated component testing and preview capabilities + +Negative: +- Requires team training and learning curve for developers unfamiliar with declarative composition patterns +- Increases APK size due to Compose runtime and foundation library dependencies +- May introduce performance overhead for complex UI hierarchies requiring recomposition optimization +- Limited interoperability with legacy XML-based layouts requires AndroidView wrappers for migration scenarios + +## Alternatives + +- Continue using XML-based layouts with View binding and imperative UI updates (rejected) + Rejected because: XML layouts require more boilerplate, lack type safety, and provide inferior testability compared to Compose's declarative approach. Evidence shows the codebase has already adopted Compose for authentication screens. + When valid: Only for maintaining existing legacy screens during gradual migration +- Adopt a hybrid approach mixing Compose and XML layouts per feature module (rejected) + Rejected because: Hybrid approaches increase cognitive load, complicate navigation patterns, and create inconsistent UI implementation patterns across the codebase + When valid: Temporarily during migration phase with clear timeline to full Compose adoption +- Use third-party declarative UI frameworks (Anko, Litho, Epoxy) (rejected) + Rejected because: Third-party frameworks lack official Android support, have smaller ecosystems, and introduce additional dependency risk. Jetpack Compose is the official Android UI toolkit with long-term Google support. + When valid: Not recommended given Compose's official status and ecosystem maturity + +## Risks + +- Performance degradation in complex UI hierarchies due to excessive recomposition or inefficient state management + Mitigation: Implement recomposition profiling in development builds, use remember and derivedStateOf appropriately, and establish performance benchmarks for critical screens + Owner: Android UI team +- Inconsistent Compose adoption patterns across feature modules leading to fragmented architecture + Mitigation: Establish Compose coding standards, provide reusable composable component library, and conduct code reviews focused on composition patterns + Owner: Architecture team +- Dependency version conflicts between Compose libraries and other androidx dependencies + Mitigation: Use Compose BOM (Bill of Materials) for version alignment, maintain dependency update schedule, and test compatibility in CI pipeline + Owner: Build and infrastructure team + +## Implementation Notes + +- Use androidx.compose.foundation.layout components (Column, Row, Box, Spacer) as primary layout primitives instead of ConstraintLayout unless complex positioning is required +- Separate screen composables (e.g., SetupUnlockScreen) from handler composables (e.g., CompleteRegistrationHandler) to maintain clear separation between UI composition and event handling logic +- Leverage androidx.compose.runtime.remember for state that should survive recomposition and androidx.compose.runtime.rememberSaveable for state that should survive configuration changes +- Integrate with ViewModel using androidx.lifecycle.viewmodel.compose.viewModel() and observe state using collectAsState() for reactive UI updates +- Use androidx.activity.compose.BackHandler for declarative back navigation handling within composable screens + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin/com/x8bit/bitwarden/ui/ --include='*.kt' | wc -l +- grep -r 'androidx.compose.foundation.layout' app/src/main/kotlin/ --include='*.kt' | grep -E '(Column|Row|Box|Spacer)' | wc -l +- find app/src/main/kotlin/com/x8bit/bitwarden/ui/ -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All screen files (*Screen.kt) in the ui/ module contain at least one @Composable function +- Layout composition uses androidx.compose.foundation.layout components rather than XML inflation +- No new XML layout files are created in feature modules covered by this ADR scope + +## Enforcement + +- Verified by: CI pipeline grep checks for @Composable annotation presence in *Screen.kt files +- Verified by: Code review checklist verification of Compose usage in new UI implementations +- Verified by: Static analysis rules detecting XML layout inflation in new feature modules +- Violation handling: CI build warnings for new screen files without @Composable annotations +- Violation handling: Code review rejection for XML-based layouts in new feature development +- Violation handling: Architecture review required for exception requests with documented justification +- Exception process: Submit exception request to architecture team with technical justification and evidence +- Exception process: Provide performance benchmarks or compatibility constraints requiring alternative approach +- Exception process: Document exception in ADR exceptions log with approval, timeline, and migration plan if applicable \ No newline at end of file diff --git a/docs/adr/9f645b4e-5542-4c5d-b627-a1751a2814c2-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-use.md b/docs/adr/9f645b4e-5542-4c5d-b627-a1751a2814c2-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-use.md new file mode 100644 index 00000000000..29ae33cfabd --- /dev/null +++ b/docs/adr/9f645b4e-5542-4c5d-b627-a1751a2814c2-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-validation-schemas-use.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Validation Schemas Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. MUST: Validation schemas MUST use z.object() with typed fields (z.number(), z.boolean(), z.string()) and MUST specify defaults using .default() where appropriate + +## Policy Block + +- MUST Validation schemas MUST use z.object() with typed fields (z.number(), z.boolean(), z.string()) and MUST specify defaults using .default() where appropriate + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/9fdc35ed-c47b-4d09-8fd2-26a59f632114-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md b/docs/adr/9fdc35ed-c47b-4d09-8fd2-26a59f632114-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md new file mode 100644 index 00000000000..45899cbedce --- /dev/null +++ b/docs/adr/9fdc35ed-c47b-4d09-8fd2-26a59f632114-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Use Androidx + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. SHOULD: Activities SHOULD use androidx.activity.viewModels delegation for ViewModel instantiation to ensure proper lifecycle scoping and configuration change survival + +## Policy Block + +- SHOULD Activities SHOULD use androidx.activity.viewModels delegation for ViewModel instantiation to ensure proper lifecycle scoping and configuration change survival + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/a0dd2b99-65aa-464c-a96f-8bf0ae9dcf2e-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-schemas-define.md b/docs/adr/a0dd2b99-65aa-464c-a96f-8bf0ae9dcf2e-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-schemas-define.md new file mode 100644 index 00000000000..0e5ad7fe226 --- /dev/null +++ b/docs/adr/a0dd2b99-65aa-464c-a96f-8bf0ae9dcf2e-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-schemas-define.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Validation Schemas Define + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. SHOULD: Validation schemas SHOULD define default values for optional parameters (e.g., .default(true), .default(2)) to ensure predictable behavior + +## Policy Block + +- SHOULD Validation schemas SHOULD define default values for optional parameters (e.g., .default(true), .default(2)) to ensure predictable behavior + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/a59d9d80-8ebf-4f68-9ead-eccacbe96b50-standardize-console-error-and-response-error-for-error-logging-in-libraries-kotlin-network-libraries.md b/docs/adr/a59d9d80-8ebf-4f68-9ead-eccacbe96b50-standardize-console-error-and-response-error-for-error-logging-in-libraries-kotlin-network-libraries.md new file mode 100644 index 00000000000..311b7bbff95 --- /dev/null +++ b/docs/adr/a59d9d80-8ebf-4f68-9ead-eccacbe96b50-standardize-console-error-and-response-error-for-error-logging-in-libraries-kotlin-network-libraries.md @@ -0,0 +1,117 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Kotlin Network Libraries + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Library modules in both TypeScript (android-device-server) and Kotlin (bitwarden network layer) implement error logging using platform-native error reporting mechanisms +- The TypeScript implementation uses console.error for tool errors and fatal errors in an MCP server context, while the Kotlin implementation uses Response.error with HTTP status codes and JSON-formatted error messages +- Both implementations integrate error logging within core library functionality, suggesting a cross-platform pattern for observable error handling in modular architectures +- The pattern appears in libraries that serve as integration points: an Android device MCP server and a network layer for API communication + +## Problem Statement + +Library modules require consistent, observable error logging mechanisms that integrate with their respective runtime environments (Node.js console for TypeScript, Retrofit Response for Kotlin) to enable debugging, monitoring, and error propagation without introducing external logging framework dependencies. + +## Decision + +1. SHOULD: Kotlin network libraries SHOULD use Response.error with appropriate HTTP status codes and JSON-formatted error messages for API-layer error responses + +## Policy Block + +- SHOULD Kotlin network libraries SHOULD use Response.error with appropriate HTTP status codes and JSON-formatted error messages for API-layer error responses + +In scope: +- TypeScript libraries running in Node.js environments with console API access +- Kotlin libraries using Retrofit for HTTP client functionality +- Library modules designed for reuse across multiple applications or services +- Error handling code paths within library boundaries + +Out of scope: +- Application-level logging infrastructure and aggregation systems +- Structured logging frameworks (Winston, Log4j, SLF4J) used by consuming applications +- Production monitoring and alerting systems external to library code +- Log persistence, rotation, or archival mechanisms + +Exceptions: +- EXC-001: Library is explicitly designed as a logging abstraction or wrapper (e.g., a logging facade library) +- EXC-002: Library operates in an environment without platform-native error logging (embedded systems, constrained runtimes) + +## Rationale + +- Platform-native error logging mechanisms (console.error, Response.error) are universally available in their respective runtime environments, eliminating external dependencies and reducing library footprint +- The pattern observed across TypeScript and Kotlin implementations demonstrates a cross-platform architectural principle: libraries should use runtime-provided error reporting rather than introducing framework coupling +- Using platform-native mechanisms enables library consumers to intercept, redirect, or enhance error logging through standard runtime hooks (console redirection, Retrofit interceptors) without modifying library code +- The evidence shows consistent integration of error logging with core library operations (tool execution, HTTP response construction), indicating error observability is treated as a first-class concern in library design + +## Consequences + +Positive: +- Reduced library dependency footprint by avoiding external logging framework dependencies +- Improved library portability across different application contexts and deployment environments +- Simplified library testing through standard console/response mocking mechanisms +- Enhanced consumer flexibility to integrate library error logging with application-specific monitoring infrastructure + +Negative: +- Limited structured logging capabilities compared to dedicated logging frameworks (no log levels, structured fields, or filtering) +- Potential inconsistency in error log format across different libraries and platforms +- Reduced observability features such as automatic context propagation, correlation IDs, or distributed tracing integration +- Console.error output may be difficult to parse or aggregate in production monitoring systems without additional tooling + +## Alternatives + +- Adopt a lightweight, cross-platform logging abstraction library (e.g., pino for TypeScript, SLF4J for Kotlin) as a standard dependency (rejected) + Rejected because: Introduces external dependency and version management complexity; conflicts with the observed pattern of using platform-native mechanisms; reduces library portability + When valid: When libraries require structured logging with log levels, filtering, and production-grade observability features that justify the dependency cost +- Implement custom logging abstraction within each library with pluggable backends (rejected) + Rejected because: Increases library code complexity and maintenance burden; duplicates logging abstraction logic across libraries; evidence shows preference for simple, direct error reporting + When valid: When building a library ecosystem with shared logging requirements and centralized logging infrastructure management +- Provide optional logging callback parameters for all error-prone operations (deferred) + Rejected because: Not observed in current evidence; would require API design changes across library interfaces + When valid: As an enhancement to enable custom error handling while maintaining platform-native defaults (see R-20-006) + +## Risks + +- Inconsistent error log formats across libraries make centralized monitoring and alerting difficult to implement + Mitigation: Establish error message format conventions (e.g., prefix patterns, JSON structure) documented in library development guidelines; provide examples of log parsing patterns for common monitoring tools + Owner: Engineering team, library maintainers +- Platform-native error logging may not provide sufficient detail for debugging complex library interactions in production + Mitigation: Ensure error messages include actionable context (operation name, input parameters, error codes); document error scenarios and troubleshooting steps in library documentation; consider optional verbose logging modes + Owner: Engineering team +- Console.error output in high-throughput scenarios may impact performance or overwhelm log aggregation systems + Mitigation: Implement error rate limiting or sampling for repetitive errors; document expected error logging volume in library performance characteristics; provide guidance on console redirection for production environments + Owner: Engineering team, SRE team + +## Implementation Notes + +- For TypeScript libraries, use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin network libraries using Retrofit, construct Response.error with appropriate HTTP status codes (e.g., HTTP_CODE_BAD_REQUEST) and JSON-formatted error messages using ResponseBody.Companion.toResponseBody +- Include sufficient context in error messages to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes +- Document expected error log output format and examples in library README to help consumers implement log parsing and monitoring + +## Continuation Context + + +Verify commands: +- grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" +- grep -r "Response\.error" --include="*.kt" src/ | head -20 +- grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l + +Accept when: +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + +## Enforcement + +- Verified by: Code review checklist verifying use of platform-native error logging mechanisms +- Verified by: Dependency analysis in CI pipeline flagging external logging framework dependencies in library modules +- Verified by: Grep-based verification commands checking for console.error and Response.error patterns in library code +- Violation handling: Code review feedback requesting removal of external logging framework dependencies and migration to platform-native mechanisms +- Violation handling: CI pipeline warnings when external logging dependencies are detected in library package manifests +- Violation handling: Architecture review required for libraries that cannot use platform-native error logging due to runtime constraints +- Exception process: Submit exception request documenting runtime environment constraints or logging requirements that cannot be met with platform-native mechanisms +- Exception process: Technical lead or architecture review approval required for exception +- Exception process: Document approved exceptions in library README with justification and alternative error reporting mechanism details \ No newline at end of file diff --git a/docs/adr/a61ccece-339e-4912-9357-9ce009aa78df-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-servers-use.md b/docs/adr/a61ccece-339e-4912-9357-9ce009aa78df-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-servers-use.md new file mode 100644 index 00000000000..701cf44d3ab --- /dev/null +++ b/docs/adr/a61ccece-339e-4912-9357-9ce009aa78df-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-servers-use.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Integration Servers Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. SHOULD: Integration servers SHOULD use stdio transport (@modelcontextprotocol/sdk/server/stdio.js) for process-based communication boundaries + +## Policy Block + +- SHOULD Integration servers SHOULD use stdio transport (@modelcontextprotocol/sdk/server/stdio.js) for process-based communication boundaries + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/a6ed72bc-a5df-4c46-9d97-33bf7399d1ae-enforce-input-validation-for-internal-api-configuration-parsers-internal-scripts-that.md b/docs/adr/a6ed72bc-a5df-4c46-9d97-33bf7399d1ae-enforce-input-validation-for-internal-api-configuration-parsers-internal-scripts-that.md new file mode 100644 index 00000000000..3359d4ac8c2 --- /dev/null +++ b/docs/adr/a6ed72bc-a5df-4c46-9d97-33bf7399d1ae-enforce-input-validation-for-internal-api-configuration-parsers-internal-scripts-that.md @@ -0,0 +1,118 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Internal Scripts That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains internal API scripts that parse external configuration data using json.load and process command-line arguments via argparse +- Configuration-driven automation scripts interact with external systems (GitHub API via subprocess) and make decisions based on parsed JSON structures +- Input validation patterns are present in the form of dictionary key access with .get() methods and exception handling for json parsing errors +- The label-pr.py script demonstrates a pattern where untrusted input (PR titles, file paths, JSON configuration) flows through validation logic before triggering actions +- The pattern reflects a security-conscious approach to internal tooling where configuration parsing includes defensive programming practices + +## Problem Statement + +Internal API scripts that consume external configuration and interact with external systems require consistent input validation to prevent injection attacks, malformed data propagation, and runtime failures when processing untrusted or semi-trusted input sources. + +## Decision + +1. MUST: Internal API scripts that parse JSON configuration files MUST use exception handling (try-except blocks) to catch json parsing errors and handle malformed input gracefully + +## Policy Block + +- MUST Internal API scripts that parse JSON configuration files MUST use exception handling (try-except blocks) to catch json parsing errors and handle malformed input gracefully + +In scope: +- Python scripts in .github/scripts/ that parse JSON configuration +- Internal automation tools that interact with external APIs (GitHub, CI/CD systems) +- Configuration-driven label assignment and PR processing workflows +- Scripts that use argparse, json.load, or subprocess modules + +Out of scope: +- Public-facing API endpoints with dedicated web frameworks +- Database query parameter validation (covered by separate ORM/query builder policies) +- Frontend form validation logic +- Third-party library internal validation + +Exceptions: +- EXC-001: Prototype or proof-of-concept scripts in development branches that are not merged to main +- EXC-002: Scripts that only process configuration files maintained exclusively by the core team with no external input + +## Rationale + +- The evidence shows a consistent pattern of defensive programming in label-pr.py using .get() methods for dictionary access and exception handling for JSON parsing, indicating an established practice worth codifying +- Internal automation scripts often bridge trusted configuration with untrusted external input (PR titles, file paths), creating a security boundary that requires explicit validation +- The use of argparse demonstrates structured input handling that prevents common injection vulnerabilities compared to raw sys.argv parsing +- Codifying this pattern reduces the risk of security vulnerabilities in internal tooling that could be exploited to manipulate CI/CD pipelines or access control systems + +## Consequences + +Positive: +- Reduced risk of injection attacks and malformed data propagation in internal automation scripts +- Consistent error handling improves debuggability and reduces runtime failures in CI/CD pipelines +- Structured argument parsing with argparse provides built-in help documentation and type validation +- Defensive dictionary access patterns prevent KeyError exceptions and improve script resilience + +Negative: +- Additional validation code increases initial development time for internal scripts +- Exception handling and safe access patterns add modest runtime overhead +- May create false sense of security if validation is incomplete or bypassed in edge cases +- Requires ongoing developer education to maintain validation practices across the team + +## Alternatives + +- Use JSON Schema validation libraries (jsonschema, pydantic) for comprehensive configuration validation (deferred) + Rejected because: null + When valid: Consider for complex configuration structures with nested objects and strict type requirements; current evidence shows simpler validation patterns are sufficient for existing use cases +- Rely on implicit Python exception handling without explicit try-except blocks (rejected) + Rejected because: Implicit exception handling provides poor error messages and makes debugging difficult; the evidence shows explicit exception handling is already practiced + When valid: Never valid for production internal APIs +- Use direct sys.argv parsing instead of argparse (rejected) + Rejected because: Direct sys.argv parsing is error-prone, lacks built-in validation, and provides no automatic help documentation; argparse is already in use and provides superior developer experience + When valid: Only acceptable for trivial single-argument scripts with no validation requirements + +## Risks + +- Incomplete validation coverage may leave security gaps if developers only validate some input paths + Mitigation: Establish code review checklist for input validation; use static analysis tools to detect unvalidated input flows + Owner: Engineering team and security reviewers +- Validation logic may become outdated as configuration schemas evolve + Mitigation: Document configuration schema alongside validation code; include validation tests in CI pipeline + Owner: Script maintainers +- Overly strict validation may break existing workflows or prevent legitimate use cases + Mitigation: Implement validation incrementally with clear error messages; provide exception process for legitimate edge cases + Owner: Engineering team + +## Implementation Notes + +- Add try-except blocks around json.load() calls with specific exception handling for JSONDecodeError to provide clear error messages +- Replace direct dictionary key access (config['key']) with safe access patterns (config.get('key', default_value)) throughout internal scripts +- Use argparse.ArgumentParser for all command-line argument parsing with explicit type specifications and help text +- Document expected configuration schema in script docstrings or adjacent README files to guide validation implementation + +## Continuation Context + + +Verify commands: +- grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' +- grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 +- find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l + +Accept when: +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries + +## Enforcement + +- Verified by: Code review checklist includes input validation verification for internal API scripts +- Verified by: Static analysis tools (pylint, bandit) configured to flag unsafe dictionary access and missing exception handling +- Verified by: CI pipeline includes grep-based validation checks for common input validation patterns +- Violation handling: Code review feedback requests addition of validation before approval +- Violation handling: CI warnings for detected validation gaps (non-blocking initially, blocking after grace period) +- Violation handling: Security review required for scripts that interact with external systems or process untrusted input +- Exception process: Developer documents the trust boundary and justification in PR description +- Exception process: Tech lead or security reviewer approves exception with explicit acknowledgment of risk +- Exception process: Exception is documented in script header comments with EXC-ID reference and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/a8900d19-7ca6-4686-8b55-c46711fdb7b8-standardize-collection-find-pattern-for-in-memory-data-queries-use-set-add.md b/docs/adr/a8900d19-7ca6-4686-8b55-c46711fdb7b8-standardize-collection-find-pattern-for-in-memory-data-queries-use-set-add.md new file mode 100644 index 00000000000..38503074a34 --- /dev/null +++ b/docs/adr/a8900d19-7ca6-4686-8b55-c46711fdb7b8-standardize-collection-find-pattern-for-in-memory-data-queries-use-set-add.md @@ -0,0 +1,100 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Use Set Add + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase demonstrates consistent use of JavaScript/TypeScript Array.find() method for querying in-memory collections across test specifications and automation scripts +- Test files in android-device-server use .find() with predicate functions to locate specific window objects by name property from parsed dumpsys output +- Python automation scripts use Set.add() operations for label and package name collection, indicating a pattern of in-memory data accumulation and membership testing +- The pattern appears in both testing contexts (vitest test suites) and operational contexts (GitHub automation scripts, JSON validation utilities) + +## Problem Statement + +Teams need a consistent, predictable approach for querying in-memory data structures to locate specific elements by property matching, particularly when working with parsed system output, configuration data, and test fixtures. Without standardization, different query patterns emerge that reduce code readability and increase cognitive load when navigating between modules. + +## Decision + +1. SHOULD: Use Set.add() for building unique collections when membership testing or duplicate prevention is required + +## Policy Block + +- SHOULD Use Set.add() for building unique collections when membership testing or duplicate prevention is required + +## Rationale + +- The pattern is observed across 3 files with 90.83% confidence, demonstrating consistent adoption in both test infrastructure and operational automation +- Array.find() provides clear semantic intent for single-element lookup operations, improving code readability compared to manual iteration +- Set.add() operations in Python scripts demonstrate parallel pattern of using language-native collection operations for membership and uniqueness constraints +- The pattern aligns with functional programming principles and modern JavaScript/TypeScript idioms, reducing imperative boilerplate + +## Consequences + +Positive: +- Improved code readability through consistent use of declarative collection query methods +- Reduced cognitive load when navigating between test specifications and automation scripts +- Better alignment with modern JavaScript/TypeScript idioms and functional programming patterns +- Clearer semantic intent in data access operations, making code review and maintenance easier + +Negative: +- Developers unfamiliar with functional array methods may require additional training or documentation +- Predicate function overhead may introduce minor performance cost compared to manual iteration in performance-critical paths +- Pattern may not extend cleanly to languages without first-class function support or equivalent collection APIs + +## Alternatives + +- Use manual for-loop iteration with conditional breaks for element lookup (rejected) + Rejected because: Manual iteration increases boilerplate code and reduces semantic clarity compared to declarative Array.find() method + When valid: Performance-critical paths where predicate function overhead is measured and significant +- Use Array.filter() followed by index access [0] for single-element lookup (rejected) + Rejected because: Array.filter() processes entire collection even after match is found, introducing unnecessary performance overhead + When valid: When subsequent operations require the filtered array or multiple matches are possible +- Use Map or Object lookup with key-based access instead of predicate-based search (deferred) + Rejected because: null + When valid: When data structure can be pre-indexed by lookup key and multiple queries justify indexing overhead + +## Risks + +- Performance degradation in large collections if .find() is used in tight loops or performance-critical paths + Mitigation: Profile data access patterns and consider pre-indexing with Map/Object for frequently queried large collections + Owner: engineering team +- Inconsistent adoption across polyglot codebase where Python, JavaScript, and TypeScript have different collection APIs + Mitigation: Document language-specific equivalents (Python: next(filter()), JavaScript/TypeScript: Array.find()) in coding standards + Owner: engineering team +- Undefined return values from .find() may cause runtime errors if not properly handled with null checks + Mitigation: Enforce TypeScript strict null checks and require explicit undefined handling in code review + Owner: engineering team + +## Implementation Notes + +- Use TypeScript strict mode to enforce null/undefined handling for .find() return values +- Consider creating utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication +- Document the pattern in coding standards with examples from dumpsys.spec.ts showing window lookup by name property +- For Python code, use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find() + +## Continuation Context + + +Verify commands: +- grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . +- grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' +- npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' + +Accept when: +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + +## Enforcement + +- Verified by: Code review checklist includes verification of collection query patterns +- Verified by: ESLint rules configured to discourage manual iteration where Array methods are applicable +- Verified by: Test coverage requirements ensure query operations are tested with expected and missing elements +- Violation handling: Code review feedback requests refactoring of manual iteration to declarative collection methods +- Violation handling: ESLint warnings flagged in CI pipeline for review before merge +- Violation handling: Documentation links provided to developers during code review for pattern examples +- Exception process: Performance-critical paths may use manual iteration if profiling demonstrates measurable impact +- Exception process: Exception requests must include benchmark data comparing Array.find() vs manual iteration +- Exception process: Approved exceptions documented inline with comments explaining performance justification \ No newline at end of file diff --git a/docs/adr/a9af7708-c42b-43f6-b33a-c7922023a6a7-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-messages-include.md b/docs/adr/a9af7708-c42b-43f6-b33a-c7922023a6a7-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-messages-include.md new file mode 100644 index 00000000000..a26c33aa935 --- /dev/null +++ b/docs/adr/a9af7708-c42b-43f6-b33a-c7922023a6a7-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-error-messages-include.md @@ -0,0 +1,114 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Error Messages Include + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements an MCP (Model Context Protocol) server using @modelcontextprotocol/sdk/server/index.js and stdio.js for communication +- Error conditions arise from both tool execution failures and fatal server-level errors requiring distinct logging contexts +- The server manages multiple tools accessed via a find pattern (tools.find(t => t.name === name)) requiring tool-scoped error identification +- Console-based logging provides immediate visibility in stdio-based server environments without external logging infrastructure dependencies +- The realtime boundary pattern (new Server with capabilities) necessitates synchronous error reporting for operational visibility + +## Problem Statement + +MCP servers operating over stdio require immediate, context-aware error logging that distinguishes between tool-level failures and fatal server errors while maintaining compatibility with the stdio transport layer and enabling operators to diagnose issues without external logging infrastructure. + +## Decision + +1. SHOULD: Error messages SHOULD include sufficient context to identify the failing component without requiring additional correlation + +## Policy Block + +- SHOULD Error messages SHOULD include sufficient context to identify the failing component without requiring additional correlation + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within the server capabilities boundary +- Fatal error conditions that terminate server operation +- Stdio-based transport layer error reporting + +Out of scope: +- Application-level logging within tool implementations +- Structured logging to external aggregation systems +- Client-side error handling and logging +- Non-error informational or debug logging + +## Rationale + +- The evidence shows explicit console.error usage for both tool-scoped errors (with name interpolation) and fatal errors, establishing a consistent pattern for synchronous error visibility +- The stdio transport layer used by @modelcontextprotocol/sdk/server/stdio.js requires console-based logging as the primary mechanism for operator visibility without interfering with protocol messages +- The tools.find pattern for tool resolution creates a natural boundary for tool-scoped error context, enabling precise error attribution +- The realtime server boundary (new Server with capabilities) necessitates immediate error reporting to maintain operational visibility during concurrent tool execution + +## Consequences + +Positive: +- Immediate error visibility in stdio-based environments without external dependencies +- Clear distinction between tool-level and server-level failures through consistent prefixing +- Simplified debugging through tool name context in error messages +- Zero-latency error reporting suitable for fatal error scenarios + +Negative: +- Console-based logging lacks structured metadata for automated analysis or aggregation +- No built-in error correlation across multiple tool invocations or server instances +- Limited filtering and search capabilities compared to structured logging systems +- Potential stderr pollution in environments with high error rates + +## Alternatives + +- Adopt structured logging library (e.g., winston, pino) with JSON output (rejected) + Rejected because: Adds external dependency and complexity for stdio-based MCP servers where console.error provides sufficient immediate visibility; structured logging better suited for long-running services with aggregation infrastructure + When valid: When MCP server operates in containerized environment with log aggregation pipeline or requires correlation across distributed tool executions +- Implement custom error event emitter with pluggable handlers (rejected) + Rejected because: Introduces abstraction overhead and delayed error reporting incompatible with fatal error scenarios requiring immediate visibility before process termination + When valid: When multiple error handling strategies must coexist or when error handling requires asynchronous processing +- Use MCP protocol error responses exclusively without console logging (rejected) + Rejected because: Protocol-level error responses do not provide operator visibility for fatal server errors or debugging during development; console logging serves distinct operational monitoring purpose + When valid: When all error handling occurs at client level and server-side operational monitoring is handled through external process supervision + +## Risks + +- Console error output may interfere with MCP protocol messages on stderr if not properly separated by transport layer + Mitigation: Verify @modelcontextprotocol/sdk/server/stdio.js properly isolates protocol messages from stderr; implement integration tests validating protocol integrity with error logging + Owner: MCP server engineering team +- Lack of structured error metadata limits automated error analysis and alerting capabilities + Mitigation: Document error message formats for parsing; consider hybrid approach with optional structured logging for production deployments while maintaining console.error baseline + Owner: Observability team +- Tool name context in error messages depends on correct name parameter propagation through tool resolution + Mitigation: Implement validation ensuring tool name is captured before execution; add fallback error logging for tool resolution failures + Owner: MCP server engineering team + +## Implementation Notes + +- Wrap all tool execution in try-catch blocks that call console.error with 'Tool error ({name}):' prefix before propagating or handling errors +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) before process exit +- Ensure tool name is captured from tools.find(t => t.name === name) result before execution to guarantee availability in error context +- Consider adding error codes or categories as structured prefixes within console.error messages to enable basic parsing without full structured logging + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ + +Accept when: +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + +## Enforcement + +- Verified by: Code review checking for console.error usage in error handling paths +- Verified by: Integration tests validating error log output format and content +- Verified by: Grep-based verification commands in CI pipeline +- Violation handling: Code review rejection for error handling without console.error logging +- Violation handling: CI pipeline warnings for missing tool name context in error logs +- Violation handling: Post-incident review when operational errors lack sufficient logging context +- Exception process: Document rationale for alternative logging approach in code comments +- Exception process: Obtain approval from observability team for structured logging adoption +- Exception process: Update ADR with amendment describing exception scope and justification \ No newline at end of file diff --git a/docs/adr/aa048d39-56ef-4832-9afe-beb1af3da70c-adopt-hilt-dependency-injection-for-android-application-components-dependencies-injected-activities.md b/docs/adr/aa048d39-56ef-4832-9afe-beb1af3da70c-adopt-hilt-dependency-injection-for-android-application-components-dependencies-injected-activities.md new file mode 100644 index 00000000000..83e36818b45 --- /dev/null +++ b/docs/adr/aa048d39-56ef-4832-9afe-beb1af3da70c-adopt-hilt-dependency-injection-for-android-application-components-dependencies-injected-activities.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Dependencies Injected Activities + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. SHOULD: Dependencies injected into Activities SHOULD use @Inject annotation for field injection rather than constructor injection + +## Policy Block + +- SHOULD Dependencies injected into Activities SHOULD use @Inject annotation for field injection rather than constructor injection + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/aae0f285-d3e2-4c79-90f6-2ba6356f3559-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-server-implementations.md b/docs/adr/aae0f285-d3e2-4c79-90f6-2ba6356f3559-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-server-implementations.md new file mode 100644 index 00000000000..96d8168dfff --- /dev/null +++ b/docs/adr/aae0f285-d3e2-4c79-90f6-2ba6356f3559-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-mcp-server-implementations.md @@ -0,0 +1,114 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Mcp Server Implementations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-mcp server implementation requires structured error reporting for tool execution failures and fatal errors +- The @modelcontextprotocol/sdk provides server infrastructure including server/index.js, server/stdio.js, and types.js modules for building MCP-compliant servers +- Console-based error logging is used for both tool-level errors (with tool name context) and fatal server errors +- The server operates in a real-time boundary context with tool discovery patterns using array find operations +- Error visibility is critical for debugging tool execution failures in the MCP server environment + +## Problem Statement + +MCP server implementations need consistent error logging that captures both tool-specific failures and fatal server errors while maintaining compatibility with the @modelcontextprotocol/sdk framework and stdio-based communication patterns. + +## Decision + +1. MUST: MCP server implementations MUST use console.error for logging tool execution errors with the format 'Tool error ({name}): {message}' + +## Policy Block + +- MUST MCP server implementations MUST use console.error for logging tool execution errors with the format 'Tool error ({name}): {message}' + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within MCP servers +- Fatal error reporting in server lifecycle +- stdio-based MCP server communication + +Out of scope: +- Client-side MCP implementations +- Structured logging frameworks (e.g., Winston, Bunyan) +- Application-level business logic logging +- Performance metrics or tracing + +## Rationale + +- The evidence shows consistent use of console.error for both tool-level and fatal errors, establishing a pattern for error visibility in MCP server contexts +- The @modelcontextprotocol/sdk provides the foundational server infrastructure, making it a core dependency for MCP server implementations +- Console-based logging aligns with stdio-based server communication patterns where structured logging frameworks might interfere with the protocol +- The pattern of including tool names in error messages provides essential context for debugging in a tool-discovery architecture + +## Consequences + +Positive: +- Simple, dependency-free error logging that works immediately without configuration +- Compatible with stdio-based MCP protocol communication without interference +- Clear error context through structured message formats including tool names +- Minimal overhead for error reporting in real-time server operations + +Negative: +- Console.error lacks structured logging capabilities (no log levels, filtering, or formatting) +- No built-in log aggregation or persistence mechanisms +- Limited observability compared to dedicated logging frameworks +- Difficult to implement log sampling or rate limiting for high-frequency errors + +## Alternatives + +- Use a structured logging framework like Winston or Pino (rejected) + Rejected because: Structured logging frameworks may interfere with stdio-based MCP protocol communication and add unnecessary dependencies for simple error reporting + When valid: When MCP servers require log aggregation, filtering, or integration with centralized logging systems +- Implement custom error handling without console output (rejected) + Rejected because: Silent error handling would eliminate visibility into tool failures and fatal errors, making debugging impossible + When valid: Never valid for server implementations requiring operational visibility +- Use process.stderr.write for direct stream writing (rejected) + Rejected because: Direct stream writing requires manual formatting and lacks the convenience of console.error while providing minimal benefit + When valid: When precise control over stderr buffering or formatting is required + +## Risks + +- Console.error output may interfere with MCP protocol messages on stdio if not properly separated + Mitigation: Ensure stderr is used for errors (console.error) while stdout is reserved for protocol messages + Owner: engineering team +- Lack of log levels makes it difficult to filter or prioritize errors in production + Mitigation: Use consistent message prefixes ('Tool error', 'Fatal error') to enable grep-based filtering + Owner: engineering team +- No log persistence means errors are lost if not captured by process supervisor + Mitigation: Deploy MCP servers with process managers that capture stderr (systemd, PM2, Docker logging) + Owner: operations team + +## Implementation Notes + +- Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities +- Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}' +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) +- Ensure the server uses stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr) + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +Accept when: +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure + +## Enforcement + +- Verified by: Code review checking for console.error usage patterns +- Verified by: Grep-based verification commands in CI pipeline +- Verified by: Runtime testing of error scenarios to verify stderr output +- Violation handling: Code review feedback requesting correction to standard error logging format +- Violation handling: CI pipeline warnings for missing or non-standard error logging +- Violation handling: Documentation updates to clarify error logging requirements +- Exception process: Request exception through architecture review for alternative logging approaches +- Exception process: Document rationale for deviation including technical constraints +- Exception process: Obtain approval from platform team before implementing alternative logging \ No newline at end of file diff --git a/docs/adr/ad140c48-3220-4bb1-9030-52b93713e782-standardize-public-contract-functions-for-github-integration-automation-functions-interacting-external.md b/docs/adr/ad140c48-3220-4bb1-9030-52b93713e782-standardize-public-contract-functions-for-github-integration-automation-functions-interacting-external.md new file mode 100644 index 00000000000..e68b6b7a1b4 --- /dev/null +++ b/docs/adr/ad140c48-3220-4bb1-9030-52b93713e782-standardize-public-contract-functions-for-github-integration-automation-functions-interacting-external.md @@ -0,0 +1,99 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Functions Interacting External + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains automation scripts for GitHub PR labeling that require structured interaction with GitHub APIs and configuration management +- Python scripts in .github/scripts/ implement integration logic using standard library modules (argparse, json, os, subprocess, sys) without external API client libraries +- The label-pr.py script exposes public contract functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that abstract GitHub CLI interactions +- Configuration-driven pattern matching against PR titles and file paths determines label application, requiring consistent data access patterns and input validation +- The automation boundary separates internal contract functions from external GitHub API calls via subprocess invocation of gh CLI + +## Problem Statement + +GitHub automation scripts require stable, testable internal APIs for configuration loading, GitHub data retrieval, and label manipulation, but ad-hoc function definitions without explicit contracts lead to inconsistent error handling, difficult testing, and fragile integration boundaries when scripts evolve or are reused across workflows. + +## Decision + +1. MUST: Functions interacting with external GitHub APIs MUST use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Policy Block + +- MUST Functions interacting with external GitHub APIs MUST use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Rationale + +- The detected pattern shows consistent naming conventions (gh_* prefix) and explicit public contracts in label-pr.py, indicating intentional API design for internal reuse and testing +- Using subprocess with gh CLI rather than direct API clients reduces dependency complexity and leverages GitHub's official CLI for authentication and API versioning +- Explicit exception handling for JSON parsing and pattern matching demonstrates defensive programming at integration boundaries where external configuration drives behavior +- Set-based label manipulation (.add() operations) prevents duplicate labels and provides efficient membership testing for conditional logic + +## Consequences + +Positive: +- Clear function contracts enable unit testing of GitHub integration logic without requiring live API access or complex mocking +- Standardized naming conventions (gh_* prefix) make integration boundaries explicit and improve code discoverability +- Subprocess-based gh CLI invocation isolates authentication complexity and API versioning from script logic +- Configuration-driven pattern matching allows non-developers to modify labeling rules without code changes + +Negative: +- Subprocess invocation of gh CLI adds latency and process overhead compared to direct HTTP API calls +- Reliance on gh CLI availability creates an external dependency that must be present in CI/CD environments +- Standard library-only constraint limits access to advanced HTTP features like connection pooling, retry logic, and structured error responses +- Set-based label manipulation requires conversion overhead when interfacing with list-based GitHub API responses + +## Alternatives + +- Use PyGithub or github3.py library for direct GitHub API access with native Python objects (rejected) + Rejected because: Introduces external dependency management complexity and requires explicit authentication token handling, whereas gh CLI provides authenticated context automatically in GitHub Actions + When valid: When scripts run outside GitHub Actions environment or require advanced API features not exposed by gh CLI +- Implement inline GitHub API calls without abstraction functions (rejected) + Rejected because: Reduces testability and code reuse, making it difficult to mock external dependencies or refactor integration logic independently + When valid: For one-off scripts with no reuse requirements and no testing needs +- Create a formal Python package with typed interfaces for GitHub integration contracts (deferred) + Rejected because: Current evidence shows single-file script usage without cross-repository reuse patterns that would justify packaging overhead + When valid: When GitHub integration patterns are reused across multiple repositories or require versioned distribution + +## Risks + +- gh CLI command interface changes could break subprocess invocations without compile-time detection + Mitigation: Pin gh CLI version in CI environment and add integration tests that verify command output format + Owner: engineering team +- Configuration JSON schema drift could cause runtime failures if validation is insufficient + Mitigation: Implement explicit schema validation for required keys (title_patterns, path_patterns) with clear error messages + Owner: engineering team +- Subprocess error handling may not capture all gh CLI failure modes (network errors, rate limits, authentication failures) + Mitigation: Wrap subprocess calls with comprehensive exception handling and log stderr output for debugging + Owner: engineering team + +## Implementation Notes + +- Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions +- Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing +- Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands +- Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed + +## Continuation Context + + +Verify commands: +- grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py +- grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py +- grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +Accept when: +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Enforcement + +- Verified by: Code review checklist verifying function naming conventions and exception handling patterns +- Verified by: Automated grep-based verification in CI pipeline checking for required function prefixes and error handling +- Violation handling: PR comments requesting refactoring to match established naming conventions +- Violation handling: CI pipeline warnings when new GitHub integration functions lack proper error handling +- Exception process: Document rationale in code comments when alternative patterns are necessary +- Exception process: Obtain approval from platform team for deviations from standard contract patterns \ No newline at end of file diff --git a/docs/adr/ae1aaeb8-5a76-49e0-9577-9342abbb66e6-enforce-schema-based-input-validation-for-public-api-endpoints-numeric-inputs-include.md b/docs/adr/ae1aaeb8-5a76-49e0-9577-9342abbb66e6-enforce-schema-based-input-validation-for-public-api-endpoints-numeric-inputs-include.md new file mode 100644 index 00000000000..303ea39caf5 --- /dev/null +++ b/docs/adr/ae1aaeb8-5a76-49e0-9577-9342abbb66e6-enforce-schema-based-input-validation-for-public-api-endpoints-numeric-inputs-include.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Numeric Inputs Include + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. SHOULD: Numeric inputs SHOULD include range constraints (min, max, nonnegative) and type constraints (int, float) appropriate to their domain + +## Policy Block + +- SHOULD Numeric inputs SHOULD include range constraints (min, max, nonnegative) and type constraints (int, float) appropriate to their domain + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/b313895b-a93e-400c-8b22-620c2abad425-standardize-set-based-label-management-for-external-client-boundaries-pattern-matching-against.md b/docs/adr/b313895b-a93e-400c-8b22-620c2abad425-standardize-set-based-label-management-for-external-client-boundaries-pattern-matching-against.md new file mode 100644 index 00000000000..1eec0ca0ff5 --- /dev/null +++ b/docs/adr/b313895b-a93e-400c-8b22-620c2abad425-standardize-set-based-label-management-for-external-client-boundaries-pattern-matching-against.md @@ -0,0 +1,115 @@ +# Standardize Set-Based Label Management for External Client Boundaries: Pattern Matching Against + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes GitHub pull request metadata to classify and label changes based on title and path patterns +- External client boundaries require dynamic label assignment based on pattern matching against configuration-driven rules +- The system uses set-based operations (.add, in-membership checks) to accumulate labels before applying them via GitHub API calls +- Configuration is loaded from JSON files and parsed using standard library modules (argparse, json, os, subprocess, sys) +- The pattern emerged in automation scripts that bridge external GitHub API interactions with internal classification logic + +## Problem Statement + +When managing labels for external client boundaries such as GitHub pull requests, the system must efficiently accumulate, deduplicate, and conditionally apply labels based on pattern matching without introducing race conditions or duplicate API calls. A consistent data access pattern is needed to handle label state transitions and batch operations. + +## Decision + +1. MUST: Pattern matching against title_patterns and path_patterns MUST be performed before label addition + +## Policy Block + +- MUST Pattern matching against title_patterns and path_patterns MUST be performed before label addition + +In scope: +- GitHub pull request labeling automation scripts +- External client boundary interactions requiring label management +- Configuration-driven pattern matching workflows +- Set-based label accumulation and deduplication logic + +Out of scope: +- Internal database label storage or persistence +- Real-time streaming label updates +- Label management for non-GitHub external systems +- Manual label assignment workflows + +## Rationale + +- Set-based operations provide O(1) deduplication and membership testing, reducing complexity in label accumulation logic +- Batching label operations before external API calls minimizes network overhead and API rate limit consumption +- Pattern-driven configuration enables declarative label rules without code changes, improving maintainability +- The evidence shows consistent use of .add() and 'in' operators across label management, indicating an established pattern + +## Consequences + +Positive: +- Automatic deduplication prevents duplicate labels from being applied to pull requests +- Reduced API calls through batching improves performance and reduces rate limit pressure +- Declarative JSON configuration enables non-developers to modify labeling rules +- Set-based operations provide clear, idiomatic Python code that is easy to test and maintain + +Negative: +- Set-based approach loses ordering information if label application order matters +- In-memory accumulation requires all labels to be determined before any can be applied +- JSON configuration parsing adds a dependency on file I/O and introduces potential parsing errors +- Pattern matching complexity grows linearly with the number of configured patterns + +## Alternatives + +- Apply labels immediately upon pattern match without accumulation (rejected) + Rejected because: Would result in multiple API calls per PR and potential race conditions with concurrent label operations + When valid: When label order must be preserved or when real-time feedback is required +- Use list-based accumulation with manual deduplication (rejected) + Rejected because: Introduces O(n) membership checks and requires explicit deduplication logic, increasing complexity + When valid: When label ordering must be preserved or when duplicate labels have semantic meaning +- Store label state in a database with transactional updates (deferred) + Rejected because: Adds infrastructure complexity and latency for a lightweight automation script + When valid: When label history tracking, auditing, or multi-step workflows are required + +## Risks + +- JSON configuration parsing errors could cause automation failures and unlabeled pull requests + Mitigation: Implement try-except blocks around json.load() calls and provide fallback behavior or alerting + Owner: engineering team +- Pattern matching complexity may degrade performance as configuration grows + Mitigation: Profile pattern matching performance and consider caching compiled patterns or using more efficient matching algorithms + Owner: engineering team +- Set-based deduplication may hide configuration errors where duplicate patterns exist + Mitigation: Add configuration validation to detect and warn about overlapping or duplicate patterns + Owner: engineering team + +## Implementation Notes + +- Initialize label sets early in the workflow to ensure all conditional branches can add labels safely +- Use descriptive variable names (e.g., labels_to_add) to distinguish accumulated sets from applied labels +- Validate JSON configuration schema on load to catch malformed patterns before runtime +- Consider logging the final label set before API calls to aid debugging and auditing +- Implement unit tests that verify set operations produce expected deduplication behavior + +## Continuation Context + + +Verify commands: +- grep -r '\.add("app:' .github/scripts/ | wc -l +- grep -r 'labels.*=.*set()' .github/scripts/ | wc -l +- python3 -m py_compile .github/scripts/label-pr.py + +Accept when: +- At least one set-based label accumulation pattern is detected in automation scripts +- Pattern matching against title_patterns or path_patterns precedes label addition +- External API calls (gh_add_labels or gh_replace_labels) are invoked after local accumulation + +## Enforcement + +- Verified by: Code review of pull request automation scripts +- Verified by: Static analysis to detect non-set-based label accumulation patterns +- Verified by: Integration tests that verify label deduplication behavior +- Violation handling: Code review feedback requesting refactoring to set-based approach +- Violation handling: CI pipeline warnings when list-based label accumulation is detected +- Violation handling: Documentation updates to clarify the standard pattern +- Exception process: Document the specific requirement that necessitates deviation (e.g., label ordering) +- Exception process: Obtain approval from the platform engineering team +- Exception process: Add inline comments explaining why the exception is necessary \ No newline at end of file diff --git a/docs/adr/b4a63d5b-ac50-4f21-82dc-20bff4ab68fc-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-accept.md b/docs/adr/b4a63d5b-ac50-4f21-82dc-20bff4ab68fc-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-accept.md new file mode 100644 index 00000000000..6a5121ab079 --- /dev/null +++ b/docs/adr/b4a63d5b-ac50-4f21-82dc-20bff4ab68fc-enforce-input-validation-for-internal-api-configuration-parsers-scripts-that-accept.md @@ -0,0 +1,118 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Scripts That Accept + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains internal API scripts that parse external configuration data using json.load and process command-line arguments via argparse +- Configuration-driven automation scripts interact with external systems (GitHub API via subprocess) and make decisions based on parsed JSON structures +- Input validation patterns are present in the form of dictionary key access with .get() methods and exception handling for json parsing errors +- The label-pr.py script demonstrates a pattern where untrusted input (PR titles, file paths, JSON configuration) flows through validation logic before triggering actions +- The pattern reflects a security-conscious approach to internal tooling where configuration parsing includes defensive programming practices + +## Problem Statement + +Internal API scripts that consume external configuration and interact with external systems require consistent input validation to prevent injection attacks, malformed data propagation, and runtime failures when processing untrusted or semi-trusted input sources. + +## Decision + +1. MUST: Scripts that accept command-line arguments MUST use argparse or equivalent structured argument parsing libraries rather than direct sys.argv manipulation + +## Policy Block + +- MUST Scripts that accept command-line arguments MUST use argparse or equivalent structured argument parsing libraries rather than direct sys.argv manipulation + +In scope: +- Python scripts in .github/scripts/ that parse JSON configuration +- Internal automation tools that interact with external APIs (GitHub, CI/CD systems) +- Configuration-driven label assignment and PR processing workflows +- Scripts that use argparse, json.load, or subprocess modules + +Out of scope: +- Public-facing API endpoints with dedicated web frameworks +- Database query parameter validation (covered by separate ORM/query builder policies) +- Frontend form validation logic +- Third-party library internal validation + +Exceptions: +- EXC-001: Prototype or proof-of-concept scripts in development branches that are not merged to main +- EXC-002: Scripts that only process configuration files maintained exclusively by the core team with no external input + +## Rationale + +- The evidence shows a consistent pattern of defensive programming in label-pr.py using .get() methods for dictionary access and exception handling for JSON parsing, indicating an established practice worth codifying +- Internal automation scripts often bridge trusted configuration with untrusted external input (PR titles, file paths), creating a security boundary that requires explicit validation +- The use of argparse demonstrates structured input handling that prevents common injection vulnerabilities compared to raw sys.argv parsing +- Codifying this pattern reduces the risk of security vulnerabilities in internal tooling that could be exploited to manipulate CI/CD pipelines or access control systems + +## Consequences + +Positive: +- Reduced risk of injection attacks and malformed data propagation in internal automation scripts +- Consistent error handling improves debuggability and reduces runtime failures in CI/CD pipelines +- Structured argument parsing with argparse provides built-in help documentation and type validation +- Defensive dictionary access patterns prevent KeyError exceptions and improve script resilience + +Negative: +- Additional validation code increases initial development time for internal scripts +- Exception handling and safe access patterns add modest runtime overhead +- May create false sense of security if validation is incomplete or bypassed in edge cases +- Requires ongoing developer education to maintain validation practices across the team + +## Alternatives + +- Use JSON Schema validation libraries (jsonschema, pydantic) for comprehensive configuration validation (deferred) + Rejected because: null + When valid: Consider for complex configuration structures with nested objects and strict type requirements; current evidence shows simpler validation patterns are sufficient for existing use cases +- Rely on implicit Python exception handling without explicit try-except blocks (rejected) + Rejected because: Implicit exception handling provides poor error messages and makes debugging difficult; the evidence shows explicit exception handling is already practiced + When valid: Never valid for production internal APIs +- Use direct sys.argv parsing instead of argparse (rejected) + Rejected because: Direct sys.argv parsing is error-prone, lacks built-in validation, and provides no automatic help documentation; argparse is already in use and provides superior developer experience + When valid: Only acceptable for trivial single-argument scripts with no validation requirements + +## Risks + +- Incomplete validation coverage may leave security gaps if developers only validate some input paths + Mitigation: Establish code review checklist for input validation; use static analysis tools to detect unvalidated input flows + Owner: Engineering team and security reviewers +- Validation logic may become outdated as configuration schemas evolve + Mitigation: Document configuration schema alongside validation code; include validation tests in CI pipeline + Owner: Script maintainers +- Overly strict validation may break existing workflows or prevent legitimate use cases + Mitigation: Implement validation incrementally with clear error messages; provide exception process for legitimate edge cases + Owner: Engineering team + +## Implementation Notes + +- Add try-except blocks around json.load() calls with specific exception handling for JSONDecodeError to provide clear error messages +- Replace direct dictionary key access (config['key']) with safe access patterns (config.get('key', default_value)) throughout internal scripts +- Use argparse.ArgumentParser for all command-line argument parsing with explicit type specifications and help text +- Document expected configuration schema in script docstrings or adjacent README files to guide validation implementation + +## Continuation Context + + +Verify commands: +- grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' +- grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 +- find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l + +Accept when: +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries + +## Enforcement + +- Verified by: Code review checklist includes input validation verification for internal API scripts +- Verified by: Static analysis tools (pylint, bandit) configured to flag unsafe dictionary access and missing exception handling +- Verified by: CI pipeline includes grep-based validation checks for common input validation patterns +- Violation handling: Code review feedback requests addition of validation before approval +- Violation handling: CI warnings for detected validation gaps (non-blocking initially, blocking after grace period) +- Violation handling: Security review required for scripts that interact with external systems or process untrusted input +- Exception process: Developer documents the trust boundary and justification in PR description +- Exception process: Tech lead or security reviewer approves exception with explicit acknowledgment of risk +- Exception process: Exception is documented in script header comments with EXC-ID reference and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/b4abce3f-6018-4a4b-a4ea-593f39ecd135-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-use-constructor.md b/docs/adr/b4abce3f-6018-4a4b-a4ea-593f39ecd135-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-use-constructor.md new file mode 100644 index 00000000000..c2850a4a6e6 --- /dev/null +++ b/docs/adr/b4abce3f-6018-4a4b-a4ea-593f39ecd135-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-use-constructor.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Viewmodels Use Constructor + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. SHOULD: ViewModels SHOULD use constructor injection rather than field injection for testability + +## Policy Block + +- SHOULD ViewModels SHOULD use constructor injection rather than field injection for testability + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/b607cb14-16bb-49df-a9c8-04f43e0c585b-standardize-console-error-and-response-error-for-error-logging-in-libraries-error-log-entries.md b/docs/adr/b607cb14-16bb-49df-a9c8-04f43e0c585b-standardize-console-error-and-response-error-for-error-logging-in-libraries-error-log-entries.md new file mode 100644 index 00000000000..8b669954532 --- /dev/null +++ b/docs/adr/b607cb14-16bb-49df-a9c8-04f43e0c585b-standardize-console-error-and-response-error-for-error-logging-in-libraries-error-log-entries.md @@ -0,0 +1,117 @@ +# Standardize console.error and Response.error for Error Logging in Libraries: Error Log Entries + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Library modules in both TypeScript (android-device-server) and Kotlin (bitwarden network layer) implement error logging using platform-native error reporting mechanisms +- The TypeScript implementation uses console.error for tool errors and fatal errors in an MCP server context, while the Kotlin implementation uses Response.error with HTTP status codes and JSON-formatted error messages +- Both implementations integrate error logging within core library functionality, suggesting a cross-platform pattern for observable error handling in modular architectures +- The pattern appears in libraries that serve as integration points: an Android device MCP server and a network layer for API communication + +## Problem Statement + +Library modules require consistent, observable error logging mechanisms that integrate with their respective runtime environments (Node.js console for TypeScript, Retrofit Response for Kotlin) to enable debugging, monitoring, and error propagation without introducing external logging framework dependencies. + +## Decision + +1. MUST: Error log entries MUST include contextual information identifying the error source (tool name, operation type, or error category) + +## Policy Block + +- MUST Error log entries MUST include contextual information identifying the error source (tool name, operation type, or error category) + +In scope: +- TypeScript libraries running in Node.js environments with console API access +- Kotlin libraries using Retrofit for HTTP client functionality +- Library modules designed for reuse across multiple applications or services +- Error handling code paths within library boundaries + +Out of scope: +- Application-level logging infrastructure and aggregation systems +- Structured logging frameworks (Winston, Log4j, SLF4J) used by consuming applications +- Production monitoring and alerting systems external to library code +- Log persistence, rotation, or archival mechanisms + +Exceptions: +- EXC-001: Library is explicitly designed as a logging abstraction or wrapper (e.g., a logging facade library) +- EXC-002: Library operates in an environment without platform-native error logging (embedded systems, constrained runtimes) + +## Rationale + +- Platform-native error logging mechanisms (console.error, Response.error) are universally available in their respective runtime environments, eliminating external dependencies and reducing library footprint +- The pattern observed across TypeScript and Kotlin implementations demonstrates a cross-platform architectural principle: libraries should use runtime-provided error reporting rather than introducing framework coupling +- Using platform-native mechanisms enables library consumers to intercept, redirect, or enhance error logging through standard runtime hooks (console redirection, Retrofit interceptors) without modifying library code +- The evidence shows consistent integration of error logging with core library operations (tool execution, HTTP response construction), indicating error observability is treated as a first-class concern in library design + +## Consequences + +Positive: +- Reduced library dependency footprint by avoiding external logging framework dependencies +- Improved library portability across different application contexts and deployment environments +- Simplified library testing through standard console/response mocking mechanisms +- Enhanced consumer flexibility to integrate library error logging with application-specific monitoring infrastructure + +Negative: +- Limited structured logging capabilities compared to dedicated logging frameworks (no log levels, structured fields, or filtering) +- Potential inconsistency in error log format across different libraries and platforms +- Reduced observability features such as automatic context propagation, correlation IDs, or distributed tracing integration +- Console.error output may be difficult to parse or aggregate in production monitoring systems without additional tooling + +## Alternatives + +- Adopt a lightweight, cross-platform logging abstraction library (e.g., pino for TypeScript, SLF4J for Kotlin) as a standard dependency (rejected) + Rejected because: Introduces external dependency and version management complexity; conflicts with the observed pattern of using platform-native mechanisms; reduces library portability + When valid: When libraries require structured logging with log levels, filtering, and production-grade observability features that justify the dependency cost +- Implement custom logging abstraction within each library with pluggable backends (rejected) + Rejected because: Increases library code complexity and maintenance burden; duplicates logging abstraction logic across libraries; evidence shows preference for simple, direct error reporting + When valid: When building a library ecosystem with shared logging requirements and centralized logging infrastructure management +- Provide optional logging callback parameters for all error-prone operations (deferred) + Rejected because: Not observed in current evidence; would require API design changes across library interfaces + When valid: As an enhancement to enable custom error handling while maintaining platform-native defaults (see R-20-006) + +## Risks + +- Inconsistent error log formats across libraries make centralized monitoring and alerting difficult to implement + Mitigation: Establish error message format conventions (e.g., prefix patterns, JSON structure) documented in library development guidelines; provide examples of log parsing patterns for common monitoring tools + Owner: Engineering team, library maintainers +- Platform-native error logging may not provide sufficient detail for debugging complex library interactions in production + Mitigation: Ensure error messages include actionable context (operation name, input parameters, error codes); document error scenarios and troubleshooting steps in library documentation; consider optional verbose logging modes + Owner: Engineering team +- Console.error output in high-throughput scenarios may impact performance or overwhelm log aggregation systems + Mitigation: Implement error rate limiting or sampling for repetitive errors; document expected error logging volume in library performance characteristics; provide guidance on console redirection for production environments + Owner: Engineering team, SRE team + +## Implementation Notes + +- For TypeScript libraries, use console.error with descriptive prefixes that identify the library name, operation, and error category (e.g., 'Tool error (${toolName}):', 'Fatal error:') +- For Kotlin network libraries using Retrofit, construct Response.error with appropriate HTTP status codes (e.g., HTTP_CODE_BAD_REQUEST) and JSON-formatted error messages using ResponseBody.Companion.toResponseBody +- Include sufficient context in error messages to enable debugging without requiring source code access: operation identifiers, input validation failures, exception types, and error codes +- Document expected error log output format and examples in library README to help consumers implement log parsing and monitoring + +## Continuation Context + + +Verify commands: +- grep -r "console\.error" --include="*.ts" --include="*.js" src/ | grep -v "node_modules" +- grep -r "Response\.error" --include="*.kt" src/ | head -20 +- grep -r "import.*logging" --include="*.ts" --include="*.kt" src/ | grep -v "obs.logging" | wc -l + +Accept when: +- Library code uses console.error (TypeScript) or Response.error (Kotlin) for error logging without importing external logging frameworks +- Error log statements include contextual information (operation name, error type, or source identifier) +- No dependencies on external logging libraries (winston, pino, log4j, slf4j) appear in library package manifests or import statements + +## Enforcement + +- Verified by: Code review checklist verifying use of platform-native error logging mechanisms +- Verified by: Dependency analysis in CI pipeline flagging external logging framework dependencies in library modules +- Verified by: Grep-based verification commands checking for console.error and Response.error patterns in library code +- Violation handling: Code review feedback requesting removal of external logging framework dependencies and migration to platform-native mechanisms +- Violation handling: CI pipeline warnings when external logging dependencies are detected in library package manifests +- Violation handling: Architecture review required for libraries that cannot use platform-native error logging due to runtime constraints +- Exception process: Submit exception request documenting runtime environment constraints or logging requirements that cannot be met with platform-native mechanisms +- Exception process: Technical lead or architecture review approval required for exception +- Exception process: Document approved exceptions in library README with justification and alternative error reporting mechanism details \ No newline at end of file diff --git a/docs/adr/b6399a6b-ae13-419a-ab12-6bfe49660899-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-annotated-hiltviewmodel.md b/docs/adr/b6399a6b-ae13-419a-ab12-6bfe49660899-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-annotated-hiltviewmodel.md new file mode 100644 index 00000000000..4ad0b1506de --- /dev/null +++ b/docs/adr/b6399a6b-ae13-419a-ab12-6bfe49660899-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-viewmodels-annotated-hiltviewmodel.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Viewmodels Annotated Hiltviewmodel + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. MUST: All ViewModels MUST be annotated with @HiltViewModel to enable dependency injection through Hilt framework + +## Policy Block + +- MUST All ViewModels MUST be annotated with @HiltViewModel to enable dependency injection through Hilt framework + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/b6ac444b-c292-4cbc-90bc-80331575d6a6-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-http-error-response.md b/docs/adr/b6ac444b-c292-4cbc-90bc-80331575d6a6-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-http-error-response.md new file mode 100644 index 00000000000..3600e80d3c6 --- /dev/null +++ b/docs/adr/b6ac444b-c292-4cbc-90bc-80331575d6a6-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-http-error-response.md @@ -0,0 +1,117 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Http Error Response + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Network error handling requires consistent testing patterns to validate error response parsing and exception mapping behavior +- The codebase uses custom exception types (CookieRedirectException, LocalNetworkAccessException) that must be converted to BitwardenError types with specific HTTP status codes +- OkHttp's Response.error() and ResponseBody.toResponseBody() provide a standard mechanism for creating mock HTTP error responses in unit tests +- JUnit 5 (@Test annotations) serves as the testing framework with assertion methods (assertEquals, assertTrue) for validating error transformation logic +- Error response bodies contain structured JSON with message and validationErrors fields that must be parsed and validated in test scenarios + +## Problem Statement + +Network layer error handling involves complex transformations between HTTP responses, custom exceptions, and domain error types. Without standardized testing patterns for error scenarios, teams may create inconsistent mock responses, fail to validate critical error parsing paths, or miss edge cases in exception-to-error mappings. This leads to fragile error handling code and potential runtime failures when unexpected HTTP error responses occur. + +## Decision + +1. MUST: HTTP error response tests MUST use OkHttp's Response.error() with ResponseBody.toResponseBody() to create mock error responses + +## Policy Block + +- MUST HTTP error response tests MUST use OkHttp's Response.error() with ResponseBody.toResponseBody() to create mock error responses + +In scope: +- Network layer unit tests in network/src/test/kotlin/**/*Test.kt +- Tests validating toBitwardenError() extension functions +- Tests validating parseErrorBodyOrNull() error parsing logic +- HTTP error response mocking for status codes 400-599 +- Custom exception type testing (CookieRedirectException, LocalNetworkAccessException) + +Out of scope: +- Integration tests with real HTTP clients +- End-to-end error handling flows +- UI layer error display testing +- Non-HTTP error scenarios (e.g., network timeouts, SSL errors) +- Production error logging implementation + +## Rationale + +- The evidence shows consistent use of Response.error() and toResponseBody() across 2 test files, indicating an established pattern for mocking HTTP error responses +- JUnit 5 assertions (assertEquals, assertTrue) provide type-safe validation of error transformations with clear failure messages +- Testing both exception-to-error mapping and JSON body parsing ensures comprehensive coverage of the error handling pipeline +- The pattern enables isolated unit testing of error logic without requiring actual network calls or HTTP server infrastructure + +## Consequences + +Positive: +- Consistent error response mocking reduces test code duplication and improves maintainability +- Type-safe assertions catch regressions in error transformation logic during refactoring +- Isolated unit tests execute quickly without network dependencies, enabling fast feedback loops +- Structured JSON validation ensures error messages and validation errors are correctly extracted for user display + +Negative: +- OkHttp-specific mocking creates tight coupling between tests and the HTTP client library +- Mock responses may diverge from actual server error formats if not kept synchronized +- Test coverage is limited to known error scenarios and may miss unexpected server responses +- Additional test code is required to maintain comprehensive error scenario coverage + +## Alternatives + +- Use MockWebServer to simulate full HTTP server responses for error testing (rejected) + Rejected because: MockWebServer adds complexity and slower test execution for unit-level error transformation logic that can be tested with simple mock objects + When valid: Integration tests requiring full request/response cycles with headers, redirects, and connection handling +- Create custom test fixtures or builders for BitwardenError instances (rejected) + Rejected because: Direct construction bypasses the actual transformation logic (toBitwardenError) that needs validation, reducing test coverage of production code paths + When valid: Tests focused on error handling behavior downstream of error creation, where the transformation itself is not under test +- Use property-based testing to generate random error responses (deferred) + Rejected because: Not currently implemented in the codebase; would require additional testing framework dependencies + When valid: Future enhancement to discover edge cases in error parsing logic with generated inputs + +## Risks + +- Mock error responses diverge from actual server API error formats over time + Mitigation: Maintain contract tests or API schema validation to ensure mock responses match production error formats; periodically review server API documentation + Owner: Network layer team +- OkHttp library updates may change Response.error() behavior or deprecate APIs + Mitigation: Pin OkHttp version in dependency management; review release notes during upgrades; maintain adapter layer if API changes + Owner: Engineering team +- Test coverage gaps for uncommon HTTP status codes or malformed response bodies + Mitigation: Use code coverage tools to identify untested error paths; add parameterized tests for status code ranges; include malformed JSON test cases + Owner: QA and development team + +## Implementation Notes + +- Import okhttp3.ResponseBody.Companion.toResponseBody and retrofit2.Response for creating mock error responses in test setup +- Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions +- Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability +- Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic) +- Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites + +## Continuation Context + + +Verify commands: +- grep -r "Response.error" network/src/test/kotlin/ | wc -l +- grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l +- grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l + +Accept when: +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields + +## Enforcement + +- Verified by: Code review checklist requiring error transformation tests for new exception types +- Verified by: CI pipeline test execution with minimum coverage thresholds for network error handling code +- Verified by: Static analysis to detect Response.error() usage patterns in test files +- Violation handling: Pull requests adding new error types without corresponding tests are blocked until tests are added +- Violation handling: Coverage drops in network error handling modules trigger build warnings and team notifications +- Violation handling: Quarterly audit of error test patterns identifies inconsistencies for remediation +- Exception process: Temporary exception granted for prototype or spike work with technical debt ticket created +- Exception process: Exception requires architecture team approval with documented rationale +- Exception process: All exceptions reviewed in monthly technical debt review meetings with remediation timeline \ No newline at end of file diff --git a/docs/adr/b80305fd-3b3e-4655-b99a-700320564144-adopt-hilt-dependency-injection-for-android-application-components-android-framework-components.md b/docs/adr/b80305fd-3b3e-4655-b99a-700320564144-adopt-hilt-dependency-injection-for-android-application-components-android-framework-components.md new file mode 100644 index 00000000000..73e16c32850 --- /dev/null +++ b/docs/adr/b80305fd-3b3e-4655-b99a-700320564144-adopt-hilt-dependency-injection-for-android-application-components-android-framework-components.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Android Framework Components + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. MUST_NOT: Android framework components MUST_NOT manually instantiate dependencies that can be provided through Hilt injection + +## Policy Block + +- MUST_NOT Android framework components MUST_NOT manually instantiate dependencies that can be provided through Hilt injection + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/b9c30d98-d40b-4301-9516-0097cc202473-adopt-async-handler-pattern-for-tool-operations-handler-functions-not.md b/docs/adr/b9c30d98-d40b-4301-9516-0097cc202473-adopt-async-handler-pattern-for-tool-operations-handler-functions-not.md new file mode 100644 index 00000000000..72d5d6498f8 --- /dev/null +++ b/docs/adr/b9c30d98-d40b-4301-9516-0097cc202473-adopt-async-handler-pattern-for-tool-operations-handler-functions-not.md @@ -0,0 +1,120 @@ +# Adopt Async Handler Pattern for Tool Operations: Handler Functions Not + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the android-device-server MCP service. + +## Context + +- The android-device-server MCP service implements multiple tool operations (capture, tap-at, find-element-pipeline) that interact with external Android Debug Bridge (adb) processes and file system operations +- Tool operations require coordination of asynchronous I/O including process execution, file reads/writes, and validation steps that cannot block the event loop +- Each tool exports a handler function that serves as the primary entry point for tool invocation, establishing a consistent interface pattern across the codebase +- The codebase uses Zod for input validation schemas and node:path/node:fs for file system operations, requiring async coordination between validation and execution phases + +## Problem Statement + +Tool operations in the android-device-server require a consistent concurrency model that coordinates asynchronous validation, external process execution, and file system operations without blocking the Node.js event loop, while maintaining a uniform interface pattern across all tool implementations. + +## Decision + +1. MUST: Handler functions MUST NOT block the Node.js event loop with synchronous I/O operations + +## Policy Block + +- MUST Handler functions MUST NOT block the Node.js event loop with synchronous I/O operations + +In scope: +- All tool implementations in the android-device-server/src/tools directory +- Handler functions that coordinate adb process execution +- Operations involving file system reads/writes via node:fs +- Tool entry points exported for MCP service consumption + +Out of scope: +- Utility functions that do not serve as tool entry points +- Synchronous helper functions for data transformation +- Type definitions and interface declarations +- Test harness and mock implementations + +Exceptions: +- EXC-001: Pure computational functions that perform synchronous transformations without I/O + +## Rationale + +- The evidence shows consistent use of async handler functions (capture, tapAt, findElementWithObstruction) across 3 tool implementations, indicating an established pattern for coordinating asynchronous operations +- All detected tools import adb utilities and validation modules, requiring async coordination between validation, process execution, and result handling +- The handler pattern provides a uniform interface for tool invocation while encapsulating the complexity of async I/O coordination with external processes and file systems +- Using async/await patterns prevents event loop blocking and enables proper error propagation in the Node.js runtime environment + +## Consequences + +Positive: +- Consistent interface pattern across all tool implementations improves code maintainability and developer onboarding +- Non-blocking async operations ensure the MCP service remains responsive during long-running adb operations +- Separation of validation and execution phases enables early input rejection before expensive I/O operations +- Async/await syntax provides clear error handling and control flow compared to callback-based patterns + +Negative: +- Async handler pattern adds complexity compared to synchronous implementations for simple operations +- Requires developers to understand Promise semantics and async/await error handling +- Potential for unhandled promise rejections if error handling is not properly implemented +- Debugging async call stacks can be more challenging than synchronous execution flows + +## Alternatives + +- Synchronous handler functions with blocking I/O operations (rejected) + Rejected because: Blocking I/O would freeze the Node.js event loop during adb process execution and file operations, making the service unresponsive to concurrent requests + When valid: Only appropriate for pure computational functions without I/O dependencies +- Callback-based asynchronous pattern using Node.js callback conventions (rejected) + Rejected because: Callback patterns lead to nested callback hell and more complex error handling compared to async/await syntax available in modern Node.js + When valid: Legacy codebases or when targeting very old Node.js versions without async/await support +- Event emitter pattern for tool operations (rejected) + Rejected because: Event emitters add unnecessary complexity for request-response tool operations that have clear start and end points + When valid: Appropriate for streaming operations or long-running processes with multiple intermediate events + +## Risks + +- Unhandled promise rejections in handler functions could crash the Node.js process or leave operations in inconsistent states + Mitigation: Implement comprehensive try-catch blocks in all async handlers and configure Node.js to log unhandled rejections. Add integration tests that verify error handling paths. + Owner: Engineering team +- Long-running adb operations could accumulate pending promises and exhaust memory if not properly managed + Mitigation: Implement timeouts for all adb operations and add monitoring for pending promise counts. Consider implementing operation queuing with concurrency limits. + Owner: Engineering team +- Inconsistent error handling patterns across handlers could lead to unpredictable failure modes + Mitigation: Establish standard error handling patterns and document them. Create shared error handling utilities that all handlers can use. + Owner: Engineering team + +## Implementation Notes + +- All new tool implementations should follow the pattern: export an async function that accepts validated parameters and returns a Promise of the operation result +- Use Zod schemas defined at module level for input validation, and validate before entering the async handler logic +- Import adb utilities and file system operations from their respective modules (../adb/adb.js, node:fs, node:path) and await their results +- Ensure all async handlers have proper error handling with try-catch blocks and meaningful error messages that include context about the failed operation + +## Continuation Context + + +Verify commands: +- grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + +## Enforcement + +- Verified by: Code review checklist requiring async handler pattern for new tools +- Verified by: ESLint rules detecting synchronous I/O operations in tool handlers +- Verified by: Integration tests verifying non-blocking behavior under concurrent load +- Violation handling: Code review rejection for synchronous I/O in handler functions +- Violation handling: CI pipeline failure on ESLint violations for blocking operations +- Violation handling: Automated comments on PRs identifying missing async/await patterns +- Exception process: Document exception rationale in ADR amendment or inline code comments +- Exception process: Obtain tech lead approval for synchronous operations in tool handlers +- Exception process: Add exception to ESLint configuration with justification comment \ No newline at end of file diff --git a/docs/adr/bc5d0ec4-e4fb-4c43-945a-977c37f92a37-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-fatal-server-level.md b/docs/adr/bc5d0ec4-e4fb-4c43-945a-977c37f92a37-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-fatal-server-level.md new file mode 100644 index 00000000000..74ae4cadb4e --- /dev/null +++ b/docs/adr/bc5d0ec4-e4fb-4c43-945a-977c37f92a37-adopt-console-based-error-logging-with-tool-scoped-context-in-mcp-servers-fatal-server-level.md @@ -0,0 +1,114 @@ +# Adopt Console-Based Error Logging with Tool-Scoped Context in MCP Servers: Fatal Server Level + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements an MCP (Model Context Protocol) server using @modelcontextprotocol/sdk/server/index.js and stdio.js for communication +- Error conditions arise from both tool execution failures and fatal server-level errors requiring distinct logging contexts +- The server manages multiple tools accessed via a find pattern (tools.find(t => t.name === name)) requiring tool-scoped error identification +- Console-based logging provides immediate visibility in stdio-based server environments without external logging infrastructure dependencies +- The realtime boundary pattern (new Server with capabilities) necessitates synchronous error reporting for operational visibility + +## Problem Statement + +MCP servers operating over stdio require immediate, context-aware error logging that distinguishes between tool-level failures and fatal server errors while maintaining compatibility with the stdio transport layer and enabling operators to diagnose issues without external logging infrastructure. + +## Decision + +1. MUST: Fatal server-level errors MUST be logged using console.error with the prefix 'Fatal error:' followed by the error object + +## Policy Block + +- MUST Fatal server-level errors MUST be logged using console.error with the prefix 'Fatal error:' followed by the error object + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within the server capabilities boundary +- Fatal error conditions that terminate server operation +- Stdio-based transport layer error reporting + +Out of scope: +- Application-level logging within tool implementations +- Structured logging to external aggregation systems +- Client-side error handling and logging +- Non-error informational or debug logging + +## Rationale + +- The evidence shows explicit console.error usage for both tool-scoped errors (with name interpolation) and fatal errors, establishing a consistent pattern for synchronous error visibility +- The stdio transport layer used by @modelcontextprotocol/sdk/server/stdio.js requires console-based logging as the primary mechanism for operator visibility without interfering with protocol messages +- The tools.find pattern for tool resolution creates a natural boundary for tool-scoped error context, enabling precise error attribution +- The realtime server boundary (new Server with capabilities) necessitates immediate error reporting to maintain operational visibility during concurrent tool execution + +## Consequences + +Positive: +- Immediate error visibility in stdio-based environments without external dependencies +- Clear distinction between tool-level and server-level failures through consistent prefixing +- Simplified debugging through tool name context in error messages +- Zero-latency error reporting suitable for fatal error scenarios + +Negative: +- Console-based logging lacks structured metadata for automated analysis or aggregation +- No built-in error correlation across multiple tool invocations or server instances +- Limited filtering and search capabilities compared to structured logging systems +- Potential stderr pollution in environments with high error rates + +## Alternatives + +- Adopt structured logging library (e.g., winston, pino) with JSON output (rejected) + Rejected because: Adds external dependency and complexity for stdio-based MCP servers where console.error provides sufficient immediate visibility; structured logging better suited for long-running services with aggregation infrastructure + When valid: When MCP server operates in containerized environment with log aggregation pipeline or requires correlation across distributed tool executions +- Implement custom error event emitter with pluggable handlers (rejected) + Rejected because: Introduces abstraction overhead and delayed error reporting incompatible with fatal error scenarios requiring immediate visibility before process termination + When valid: When multiple error handling strategies must coexist or when error handling requires asynchronous processing +- Use MCP protocol error responses exclusively without console logging (rejected) + Rejected because: Protocol-level error responses do not provide operator visibility for fatal server errors or debugging during development; console logging serves distinct operational monitoring purpose + When valid: When all error handling occurs at client level and server-side operational monitoring is handled through external process supervision + +## Risks + +- Console error output may interfere with MCP protocol messages on stderr if not properly separated by transport layer + Mitigation: Verify @modelcontextprotocol/sdk/server/stdio.js properly isolates protocol messages from stderr; implement integration tests validating protocol integrity with error logging + Owner: MCP server engineering team +- Lack of structured error metadata limits automated error analysis and alerting capabilities + Mitigation: Document error message formats for parsing; consider hybrid approach with optional structured logging for production deployments while maintaining console.error baseline + Owner: Observability team +- Tool name context in error messages depends on correct name parameter propagation through tool resolution + Mitigation: Implement validation ensuring tool name is captured before execution; add fallback error logging for tool resolution failures + Owner: MCP server engineering team + +## Implementation Notes + +- Wrap all tool execution in try-catch blocks that call console.error with 'Tool error ({name}):' prefix before propagating or handling errors +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) before process exit +- Ensure tool name is captured from tools.find(t => t.name === name) result before execution to guarantee availability in error context +- Consider adding error codes or categories as structured prefixes within console.error messages to enable basic parsing without full structured logging + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "tools\.find.*name" .claude/mcp/android-device-server/src/ + +Accept when: +- All tool execution error paths include console.error calls with tool name context +- Fatal error handlers log to console.error before process termination +- Tool resolution using tools.find pattern is followed by error handling with captured tool name + +## Enforcement + +- Verified by: Code review checking for console.error usage in error handling paths +- Verified by: Integration tests validating error log output format and content +- Verified by: Grep-based verification commands in CI pipeline +- Violation handling: Code review rejection for error handling without console.error logging +- Violation handling: CI pipeline warnings for missing tool name context in error logs +- Violation handling: Post-incident review when operational errors lack sufficient logging context +- Exception process: Document rationale for alternative logging approach in code comments +- Exception process: Obtain approval from observability team for structured logging adoption +- Exception process: Update ADR with amendment describing exception scope and justification \ No newline at end of file diff --git a/docs/adr/bc783d9d-976e-45d9-89e6-30ff07dcef64-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-requiring-dependency.md b/docs/adr/bc783d9d-976e-45d9-89e6-30ff07dcef64-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-requiring-dependency.md new file mode 100644 index 00000000000..a836359886d --- /dev/null +++ b/docs/adr/bc783d9d-976e-45d9-89e6-30ff07dcef64-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-viewmodels-requiring-dependency.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Viewmodels Requiring Dependency + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. MUST: All ViewModels requiring dependency injection MUST be annotated with @HiltViewModel and use constructor injection + +## Policy Block + +- MUST All ViewModels requiring dependency injection MUST be annotated with @HiltViewModel and use constructor injection + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/be5d07aa-1fe6-479b-af16-ce09f73ce4b6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-additional-validation-constraints.md b/docs/adr/be5d07aa-1fe6-479b-af16-ce09f73ce4b6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-additional-validation-constraints.md new file mode 100644 index 00000000000..abec239db92 --- /dev/null +++ b/docs/adr/be5d07aa-1fe6-479b-af16-ce09f73ce4b6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-additional-validation-constraints.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Additional Validation Constraints + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. MAY: Additional validation constraints MAY be applied for domain-specific requirements such as minimum wait times (z.number().min(0)) or path pattern matching + +## Policy Block + +- MAY Additional validation constraints MAY be applied for domain-specific requirements such as minimum wait times (z.number().min(0)) or path pattern matching + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/bf0002f3-6984-42b2-aca2-730034c01e8b-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-inherit.md b/docs/adr/bf0002f3-6984-42b2-aca2-730034c01e8b-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-inherit.md new file mode 100644 index 00000000000..a5be52e4ac5 --- /dev/null +++ b/docs/adr/bf0002f3-6984-42b2-aca2-730034c01e8b-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-inherit.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Classes Inherit + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. MUST: All test classes MUST inherit from unittest.TestCase to provide standardized test discovery and execution + +## Policy Block + +- MUST All test classes MUST inherit from unittest.TestCase to provide standardized test discovery and execution + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/c091855f-fd5f-46da-b033-7a6ab3a1fa54-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-dialog-loading-states.md b/docs/adr/c091855f-fd5f-46da-b033-7a6ab3a1fa54-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-dialog-loading-states.md new file mode 100644 index 00000000000..25a3342cdba --- /dev/null +++ b/docs/adr/c091855f-fd5f-46da-b033-7a6ab3a1fa54-adopt-hilt-viewmodel-with-mutablestateflow-update-pattern-for-state-management-dialog-loading-states.md @@ -0,0 +1,134 @@ +# Adopt Hilt ViewModel with MutableStateFlow Update Pattern for State Management: Dialog Loading States + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Android ViewModel implementations in the codebase. + +## Context + +- The codebase uses Hilt dependency injection framework with Android ViewModels to manage UI state across configuration changes and lifecycle events +- State management requires thread-safe, immutable updates to UI state objects that are observed by composable UI components +- ViewModels coordinate between domain services and UI layers, requiring a consistent pattern for state mutations that preserves immutability +- The pattern uses SavedStateHandle for state restoration and viewModelScope for coroutine lifecycle management tied to ViewModel lifecycle +- Three ViewModels (MasterPasswordHintViewModel, MainViewModel, EnvironmentViewModel) demonstrate consistent use of mutableStateFlow.update with copy operations for state transitions + +## Problem Statement + +Android ViewModels require a consistent, thread-safe mechanism to update UI state in response to user actions and asynchronous operations while maintaining immutability guarantees, supporting state restoration across process death, and enabling reactive UI updates through observable state flows. + +## Decision + +1. SHOULD: Dialog and loading states SHOULD be modeled as sealed classes within the state object to enable exhaustive when expressions + +## Policy Block + +- SHOULD Dialog and loading states SHOULD be modeled as sealed classes within the state object to enable exhaustive when expressions + +In scope: +- All Android ViewModel classes in the app module +- UI state management for authentication flows (MasterPasswordHintViewModel, EnvironmentViewModel) +- Application-level state coordination (MainViewModel) +- State objects representing dialog states, loading states, and error states +- Coroutine-based asynchronous operations within ViewModels + +Out of scope: +- Repository layer state management +- Domain service implementations +- Compose UI components and their local state +- Non-Android platform code +- Background service state management + +Exceptions: +- EXC-001: Legacy ViewModels being migrated from older state management patterns +- EXC-002: ViewModels managing purely ephemeral state that does not require restoration + +## Rationale + +- The pattern appears consistently across 3 ViewModels with 91.20% confidence, indicating established architectural convention +- MutableStateFlow.update provides atomic compare-and-swap semantics that prevent race conditions in concurrent state updates +- Immutable data classes with copy operations ensure state transitions are predictable and debuggable through state history +- Hilt integration reduces boilerplate and ensures ViewModels receive properly scoped dependencies without manual factory creation +- The pattern aligns with Android Architecture Components best practices and Kotlin coroutines flow APIs + +## Consequences + +Positive: +- Thread-safe state updates without explicit synchronization or locking mechanisms +- Predictable state transitions through immutable data structures and functional update patterns +- Automatic lifecycle management and coroutine cancellation through viewModelScope +- Simplified dependency injection and testing through Hilt framework integration +- State restoration across process death through Parcelable implementation and SavedStateHandle + +Negative: +- Increased memory allocation from creating new state objects on every update operation +- Hilt annotation processing adds build-time overhead and generated code complexity +- Learning curve for developers unfamiliar with Kotlin Flow APIs and functional state update patterns +- Potential performance impact for high-frequency state updates due to copy operations on large state objects + +## Alternatives + +- Use LiveData with MutableLiveData for state management instead of StateFlow (rejected) + Rejected because: LiveData is lifecycle-aware but lacks the composability and operator support of Kotlin Flow, and does not integrate as cleanly with coroutines + When valid: Legacy codebases already heavily invested in LiveData where migration cost outweighs benefits +- Use manual dependency injection with ViewModel factories instead of Hilt (rejected) + Rejected because: Manual factory creation increases boilerplate and error potential, while Hilt provides compile-time validation and scoping + When valid: Small applications with minimal dependency graphs where Hilt overhead is not justified +- Use MVI architecture with sealed class actions and reducers for state updates (deferred) + Rejected because: Not rejected; represents a more structured approach that could be layered on top of current pattern + When valid: Complex ViewModels with many state transitions that would benefit from explicit action modeling and time-travel debugging + +## Risks + +- Performance degradation in ViewModels with large state objects or high-frequency updates due to repeated copy operations + Mitigation: Profile state update performance in critical paths; consider breaking large state objects into smaller, independently updatable flows; use structural sharing libraries if needed + Owner: Engineering team +- Inconsistent state update patterns if developers bypass mutableStateFlow.update and directly assign value property + Mitigation: Enforce through code review guidelines and static analysis rules; provide linting rules to detect direct value assignments; document pattern in architecture guidelines + Owner: Architecture team +- Hilt dependency injection failures at runtime due to missing bindings or scope mismatches + Mitigation: Leverage Hilt compile-time validation; establish clear module organization conventions; provide troubleshooting documentation for common Hilt errors + Owner: Platform team + +## Implementation Notes + +- Annotate ViewModel classes with @HiltViewModel and inject dependencies via @Inject constructor +- Define state as a Parcelable data class with all properties immutable (val); use sealed classes for variant states like dialogs +- Initialize MutableStateFlow with initial state, typically from SavedStateHandle or default values +- Use mutableStateFlow.update { it.copy(property = newValue) } for all state mutations to ensure atomicity +- Launch coroutines within viewModelScope for asynchronous operations; update state in response to results +- Expose state to UI as StateFlow using stateIn or asStateFlow to prevent external mutations +- Test ViewModels by collecting state flow emissions and asserting on state transitions + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r 'mutableStateFlow\.update' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r ': Parcelable' app/src/main/kotlin --include='*State.kt' | wc -l +- grep -r 'viewModelScope' app/src/main/kotlin --include='*ViewModel.kt' | wc -l + +Accept when: +- All ViewModel classes contain @HiltViewModel annotation and use constructor injection +- State updates use mutableStateFlow.update with copy operations rather than direct value assignment +- State classes implement Parcelable interface for restoration support +- Asynchronous operations execute within viewModelScope for proper lifecycle management + +## Enforcement + +- Verified by: Code review checklist verification for new ViewModel implementations +- Verified by: Static analysis rules detecting direct MutableStateFlow value assignments +- Verified by: CI pipeline checks for @HiltViewModel annotation presence on ViewModel classes +- Verified by: Unit test coverage requirements for state transition logic +- Violation handling: CI build warnings for ViewModels missing @HiltViewModel annotation +- Violation handling: Code review rejection for state updates not using mutableStateFlow.update pattern +- Violation handling: Architecture review required for ViewModels with non-Parcelable state classes +- Violation handling: Refactoring tickets created for legacy ViewModels not following pattern +- Exception process: Document exception rationale in ADR exception log with EXC-ID reference +- Exception process: Obtain architecture team approval for deviations from core pattern +- Exception process: Add code comments explaining why standard pattern is not applicable +- Exception process: Schedule technical debt review for temporary exceptions with migration timeline \ No newline at end of file diff --git a/docs/adr/c0da1b83-7641-4636-94f2-6b7299cbd587-adopt-model-context-protocol-sdk-for-android-device-integration-validation-utilities-separated.md b/docs/adr/c0da1b83-7641-4636-94f2-6b7299cbd587-adopt-model-context-protocol-sdk-for-android-device-integration-validation-utilities-separated.md new file mode 100644 index 00000000000..55fa1394e90 --- /dev/null +++ b/docs/adr/c0da1b83-7641-4636-94f2-6b7299cbd587-adopt-model-context-protocol-sdk-for-android-device-integration-validation-utilities-separated.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Validation Utilities Separated + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. SHOULD: Validation utilities SHOULD be separated into dedicated modules (e.g., ./utils/validation.js) + +## Policy Block + +- SHOULD Validation utilities SHOULD be separated into dedicated modules (e.g., ./utils/validation.js) + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/c0e01dbb-c7d8-4249-9ff1-6b54930f33e1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-screen-level-implementations.md b/docs/adr/c0e01dbb-c7d8-4249-9ff1-6b54930f33e1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-screen-level-implementations.md new file mode 100644 index 00000000000..5f847bf5fb9 --- /dev/null +++ b/docs/adr/c0e01dbb-c7d8-4249-9ff1-6b54930f33e1-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-screen-level-implementations.md @@ -0,0 +1,123 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Screen Level Implementations + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all UI component development in the Android application codebase. + +## Context + +- The Android application uses Jetpack Compose as the declarative UI framework, requiring the @Composable annotation to mark functions that emit UI elements +- Three screen implementation files in the auth feature module (SetupUnlockScreen.kt, ExpiredRegistrationLinkScreen.kt, CompleteRegistrationHandler.kt) consistently use @Composable functions with androidx.compose.* foundation and runtime libraries +- The codebase demonstrates a pattern of composing UI hierarchies using androidx.compose.foundation.layout components (Column, Row, Spacer) and androidx.compose.runtime utilities (remember, Composable) +- The detection spans authentication-related UI screens, indicating organization-wide adoption of Compose for user-facing interface construction + +## Problem Statement + +Android UI development requires a consistent framework for declaring composable UI components that integrate with the Jetpack Compose runtime, ensuring proper recomposition behavior, state management, and layout composition across all screen implementations. + +## Decision + +1. MUST: Screen-level UI implementations MUST use androidx.compose.foundation.layout components (Column, Row, Spacer, etc.) for layout composition + +## Policy Block + +- MUST Screen-level UI implementations MUST use androidx.compose.foundation.layout components (Column, Row, Spacer, etc.) for layout composition + +In scope: +- All Android UI screen implementations in app/src/main/kotlin UI packages +- Authentication feature module UI components +- Any function that directly or indirectly emits Compose UI elements +- Handler components that coordinate UI composition with ViewModels + +Out of scope: +- ViewModel classes and business logic layers +- Data repository and network layer implementations +- Utility functions that do not emit UI +- Android View system components (legacy XML-based UI) +- Unit test files and test utilities + +Exceptions: +- EXC-001: Interoperating with legacy Android View system components during migration +- EXC-002: Preview functions for Android Studio Compose preview tooling + +## Rationale + +- Evidence from 3 files shows consistent use of @Composable annotation with 92.50% confidence, indicating established organizational practice +- Jetpack Compose provides declarative UI construction with automatic recomposition, reducing boilerplate and state synchronization complexity compared to imperative View system +- The androidx.compose.foundation and androidx.compose.runtime libraries form the core dependency set observed across all detected files, establishing a stable API surface +- Standardizing on @Composable annotation ensures compile-time verification of composable function constraints and enables Compose compiler optimizations + +## Consequences + +Positive: +- Declarative UI composition reduces state management complexity and eliminates manual view updates +- Compose compiler enforces composable function constraints at compile-time, catching errors early +- Consistent use of androidx.compose.* libraries provides a unified API surface for UI development +- Improved developer productivity through reduced boilerplate and better tooling support (preview, inspection) + +Negative: +- Requires learning curve for developers familiar with traditional Android View system +- Increases APK size due to Compose runtime library dependencies +- Limited interoperability with legacy View-based components requires AndroidView wrappers +- Compose compiler plugin adds build time overhead for annotation processing + +## Alternatives + +- Continue using traditional Android View system with XML layouts and findViewById (rejected) + Rejected because: Imperative View system requires manual state synchronization, increases boilerplate, and lacks compile-time UI verification. Evidence shows organization has already committed to Compose. + When valid: Only for legacy modules not yet migrated or when specific View components have no Compose equivalent +- Adopt alternative declarative UI frameworks (Flutter, React Native) (rejected) + Rejected because: Would require complete platform rewrite and abandonment of native Android tooling. Evidence shows deep integration with androidx.compose.* libraries. + When valid: For new greenfield projects with cross-platform requirements from inception +- Hybrid approach mixing Compose and View system components (deferred) + Rejected because: Not rejected but deferred as a migration strategy. Evidence shows pure Compose adoption in detected files. + When valid: During migration period for legacy screens not yet converted to Compose + +## Risks + +- Compose API instability or breaking changes in androidx.compose.* libraries during version upgrades + Mitigation: Pin Compose library versions in dependency management, test thoroughly before upgrading, monitor Compose release notes + Owner: Android platform team +- Performance degradation from excessive recomposition in complex UI hierarchies + Mitigation: Use remember, derivedStateOf, and key() appropriately, profile with Compose Layout Inspector, follow Compose performance best practices + Owner: Engineering team +- Developer knowledge gap leading to anti-patterns or misuse of Composable functions + Mitigation: Provide Compose training, establish code review guidelines, create internal documentation and examples + Owner: Engineering team and tech leads + +## Implementation Notes + +- Import androidx.compose.runtime.Composable explicitly in all UI component files +- Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives +- Integrate androidx.compose.runtime.remember for state that should survive recomposition +- Follow naming convention of PascalCase for Composable functions to distinguish from regular functions +- Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l +- grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l +- find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation (verify via static analysis or code review) + +## Enforcement + +- Verified by: Automated static analysis via Compose compiler checks during build +- Verified by: Code review checklist requiring @Composable annotation for UI functions +- Verified by: CI pipeline grep verification counting @Composable usage in UI packages +- Violation handling: Build failure if Composable functions violate compiler constraints (e.g., calling composables from non-composable context) +- Violation handling: Code review rejection for UI functions missing @Composable annotation +- Violation handling: Automated linting warnings for missing androidx.compose.runtime.Composable imports +- Exception process: Submit exception request to architecture team with justification for non-Compose UI approach +- Exception process: Document legacy View system usage in migration tracking system +- Exception process: Obtain approval from tech lead for interop scenarios requiring AndroidView wrappers \ No newline at end of file diff --git a/docs/adr/c1294673-f723-4fa2-9d29-ed728b1b02f2-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-external.md b/docs/adr/c1294673-f723-4fa2-9d29-ed728b1b02f2-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-external.md new file mode 100644 index 00000000000..70c6ac179f8 --- /dev/null +++ b/docs/adr/c1294673-f723-4fa2-9d29-ed728b1b02f2-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-handling-external.md @@ -0,0 +1,116 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Handling External + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Three ViewModel implementations (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel) consistently use HiltViewModel annotation for dependency injection at public API boundaries handling Android Intent-based interactions +- All three ViewModels extend BaseViewModel and coordinate external API contracts through sealed action types (CredentialProviderAction, AuthCallbackAction) and data classes for Intent processing +- The pattern appears in ViewModels managing authentication flows, credential provider operations, and autofill callbacks, indicating a standardized approach to handling Android system integration points +- Dependencies injected include AuthRepository, BitwardenCredentialManager, and CredentialProviderRequestManager, suggesting a consistent architectural layer for external API coordination + +## Problem Statement + +Android ViewModels serving as public API boundaries for system integrations (credential providers, authentication callbacks, autofill) require consistent dependency injection to ensure testability, lifecycle management, and separation of concerns. Without a standardized DI approach, these critical integration points risk inconsistent initialization, difficult testing, and tight coupling to Android framework components. + +## Decision + +1. SHOULD: ViewModels handling external API contracts SHOULD use data classes for Intent payload representation + +## Policy Block + +- SHOULD ViewModels handling external API contracts SHOULD use data classes for Intent payload representation + +In scope: +- Android ViewModels handling credential provider APIs +- ViewModels processing authentication callback Intents +- ViewModels coordinating autofill service interactions +- Any ViewModel serving as boundary between Android system services and application logic + +Out of scope: +- Internal ViewModels not exposed to Android system APIs +- Fragment or Activity ViewModels handling only UI state +- Repository or manager layer components +- Non-Android platform integrations + +Exceptions: +- EXC-001: Legacy ViewModels predating Hilt adoption that require gradual migration + +## Rationale + +- Evidence shows 100% consistency across three distinct public API boundary ViewModels (credential provider, auth callback, autofill), indicating an established architectural pattern with 91.70% confidence +- HiltViewModel annotation provides Android-aware dependency injection that respects ViewModel lifecycle and survives configuration changes, critical for Intent-based system integrations +- Sealed action types and data classes create type-safe contracts that prevent runtime errors at public API boundaries where external systems interact with application logic +- Injected repository and manager components enable testability by allowing mock implementations during unit testing of Intent processing logic + +## Consequences + +Positive: +- Consistent dependency injection pattern across all public API boundary ViewModels improves maintainability and reduces cognitive load +- HiltViewModel lifecycle management prevents memory leaks and ensures proper cleanup of resources during configuration changes +- Testability improves through constructor injection, enabling unit tests with mock repositories without Android framework dependencies +- Type-safe sealed action contracts prevent runtime errors from malformed Intent data at system integration boundaries + +Negative: +- Introduces Hilt framework dependency for all public API ViewModels, increasing build complexity and annotation processing time +- Developers must understand Hilt scoping and lifecycle rules to correctly implement ViewModels at public API boundaries +- Migration of existing ViewModels to HiltViewModel pattern requires refactoring and testing effort +- Sealed action types increase boilerplate code compared to direct Intent parameter passing + +## Alternatives + +- Use manual ViewModel factory pattern with direct constructor injection (rejected) + Rejected because: Manual factory pattern requires boilerplate for each ViewModel and does not integrate with Android lifecycle-aware components as seamlessly as Hilt + When valid: In projects without Hilt or when minimizing annotation processing overhead is critical +- Use Dagger without Hilt for ViewModel injection (rejected) + Rejected because: Dagger alone requires more boilerplate and manual component management compared to Hilt's Android-specific optimizations + When valid: In projects with existing Dagger infrastructure where Hilt migration cost is prohibitive +- Use service locator pattern for dependency resolution in ViewModels (rejected) + Rejected because: Service locator pattern hides dependencies, reduces testability, and creates runtime dependency resolution failures instead of compile-time errors + When valid: Never recommended for new code; only acceptable in legacy codebases during gradual migration + +## Risks + +- Hilt annotation processing failures could break builds for all public API ViewModels simultaneously + Mitigation: Maintain Hilt version compatibility matrix, use Gradle dependency locking, and implement CI build verification for annotation processing + Owner: Engineering team +- Developers unfamiliar with Hilt may incorrectly scope dependencies, causing memory leaks or premature disposal + Mitigation: Provide ViewModel dependency injection guidelines, code review checklist, and automated lint rules to detect incorrect scoping + Owner: Architecture team +- Sealed action types may grow complex as public API contracts evolve, reducing maintainability + Mitigation: Establish action type design guidelines limiting nesting depth, use composition over inheritance, and refactor when action hierarchies exceed three levels + Owner: Engineering team + +## Implementation Notes + +- Annotate all public API boundary ViewModels with @HiltViewModel and ensure constructor parameters are annotated with @Inject +- Define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic +- Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel +- Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l +- grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l +- find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l + +Accept when: +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters + +## Enforcement + +- Verified by: Code review checklist requiring HiltViewModel annotation for all public API boundary ViewModels +- Verified by: Custom lint rule detecting ViewModels with Intent parameters lacking @HiltViewModel annotation +- Verified by: CI pipeline verification step running grep commands to validate pattern compliance +- Violation handling: CI build fails if public API ViewModels lack @HiltViewModel annotation +- Violation handling: Code review blocks merge if sealed action types are not used for Intent-based contracts +- Violation handling: Architecture team notified of violations for pattern compliance tracking +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in ADR exceptions registry with approval date and review schedule +- Exception process: Re-evaluate exception quarterly to assess migration feasibility \ No newline at end of file diff --git a/docs/adr/c30bec5f-0d33-43b4-b42b-6cea3b39c20a-enforce-input-validation-for-internal-api-configuration-parsers-configuration-parsers-use.md b/docs/adr/c30bec5f-0d33-43b4-b42b-6cea3b39c20a-enforce-input-validation-for-internal-api-configuration-parsers-configuration-parsers-use.md new file mode 100644 index 00000000000..2006e9a8465 --- /dev/null +++ b/docs/adr/c30bec5f-0d33-43b4-b42b-6cea3b39c20a-enforce-input-validation-for-internal-api-configuration-parsers-configuration-parsers-use.md @@ -0,0 +1,118 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Configuration Parsers Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains internal API scripts that parse external configuration data using json.load and process command-line arguments via argparse +- Configuration-driven automation scripts interact with external systems (GitHub API via subprocess) and make decisions based on parsed JSON structures +- Input validation patterns are present in the form of dictionary key access with .get() methods and exception handling for json parsing errors +- The label-pr.py script demonstrates a pattern where untrusted input (PR titles, file paths, JSON configuration) flows through validation logic before triggering actions +- The pattern reflects a security-conscious approach to internal tooling where configuration parsing includes defensive programming practices + +## Problem Statement + +Internal API scripts that consume external configuration and interact with external systems require consistent input validation to prevent injection attacks, malformed data propagation, and runtime failures when processing untrusted or semi-trusted input sources. + +## Decision + +1. MUST: Configuration parsers MUST use safe dictionary access methods (.get() with defaults or explicit key existence checks) when extracting values from parsed JSON structures + +## Policy Block + +- MUST Configuration parsers MUST use safe dictionary access methods (.get() with defaults or explicit key existence checks) when extracting values from parsed JSON structures + +In scope: +- Python scripts in .github/scripts/ that parse JSON configuration +- Internal automation tools that interact with external APIs (GitHub, CI/CD systems) +- Configuration-driven label assignment and PR processing workflows +- Scripts that use argparse, json.load, or subprocess modules + +Out of scope: +- Public-facing API endpoints with dedicated web frameworks +- Database query parameter validation (covered by separate ORM/query builder policies) +- Frontend form validation logic +- Third-party library internal validation + +Exceptions: +- EXC-001: Prototype or proof-of-concept scripts in development branches that are not merged to main +- EXC-002: Scripts that only process configuration files maintained exclusively by the core team with no external input + +## Rationale + +- The evidence shows a consistent pattern of defensive programming in label-pr.py using .get() methods for dictionary access and exception handling for JSON parsing, indicating an established practice worth codifying +- Internal automation scripts often bridge trusted configuration with untrusted external input (PR titles, file paths), creating a security boundary that requires explicit validation +- The use of argparse demonstrates structured input handling that prevents common injection vulnerabilities compared to raw sys.argv parsing +- Codifying this pattern reduces the risk of security vulnerabilities in internal tooling that could be exploited to manipulate CI/CD pipelines or access control systems + +## Consequences + +Positive: +- Reduced risk of injection attacks and malformed data propagation in internal automation scripts +- Consistent error handling improves debuggability and reduces runtime failures in CI/CD pipelines +- Structured argument parsing with argparse provides built-in help documentation and type validation +- Defensive dictionary access patterns prevent KeyError exceptions and improve script resilience + +Negative: +- Additional validation code increases initial development time for internal scripts +- Exception handling and safe access patterns add modest runtime overhead +- May create false sense of security if validation is incomplete or bypassed in edge cases +- Requires ongoing developer education to maintain validation practices across the team + +## Alternatives + +- Use JSON Schema validation libraries (jsonschema, pydantic) for comprehensive configuration validation (deferred) + Rejected because: null + When valid: Consider for complex configuration structures with nested objects and strict type requirements; current evidence shows simpler validation patterns are sufficient for existing use cases +- Rely on implicit Python exception handling without explicit try-except blocks (rejected) + Rejected because: Implicit exception handling provides poor error messages and makes debugging difficult; the evidence shows explicit exception handling is already practiced + When valid: Never valid for production internal APIs +- Use direct sys.argv parsing instead of argparse (rejected) + Rejected because: Direct sys.argv parsing is error-prone, lacks built-in validation, and provides no automatic help documentation; argparse is already in use and provides superior developer experience + When valid: Only acceptable for trivial single-argument scripts with no validation requirements + +## Risks + +- Incomplete validation coverage may leave security gaps if developers only validate some input paths + Mitigation: Establish code review checklist for input validation; use static analysis tools to detect unvalidated input flows + Owner: Engineering team and security reviewers +- Validation logic may become outdated as configuration schemas evolve + Mitigation: Document configuration schema alongside validation code; include validation tests in CI pipeline + Owner: Script maintainers +- Overly strict validation may break existing workflows or prevent legitimate use cases + Mitigation: Implement validation incrementally with clear error messages; provide exception process for legitimate edge cases + Owner: Engineering team + +## Implementation Notes + +- Add try-except blocks around json.load() calls with specific exception handling for JSONDecodeError to provide clear error messages +- Replace direct dictionary key access (config['key']) with safe access patterns (config.get('key', default_value)) throughout internal scripts +- Use argparse.ArgumentParser for all command-line argument parsing with explicit type specifications and help text +- Document expected configuration schema in script docstrings or adjacent README files to guide validation implementation + +## Continuation Context + + +Verify commands: +- grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' +- grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 +- find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l + +Accept when: +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries + +## Enforcement + +- Verified by: Code review checklist includes input validation verification for internal API scripts +- Verified by: Static analysis tools (pylint, bandit) configured to flag unsafe dictionary access and missing exception handling +- Verified by: CI pipeline includes grep-based validation checks for common input validation patterns +- Violation handling: Code review feedback requests addition of validation before approval +- Violation handling: CI warnings for detected validation gaps (non-blocking initially, blocking after grace period) +- Violation handling: Security review required for scripts that interact with external systems or process untrusted input +- Exception process: Developer documents the trust boundary and justification in PR description +- Exception process: Tech lead or security reviewer approves exception with explicit acknowledgment of risk +- Exception process: Exception is documented in script header comments with EXC-ID reference and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/c36190bb-c866-44bd-a3af-c6a04e54d73b-use-json-builder-dsl-for-test-assertion-construction-tests-use-buildjsonobject.md b/docs/adr/c36190bb-c866-44bd-a3af-c6a04e54d73b-use-json-builder-dsl-for-test-assertion-construction-tests-use-buildjsonobject.md new file mode 100644 index 00000000000..ccaf4b6cf89 --- /dev/null +++ b/docs/adr/c36190bb-c866-44bd-a3af-c6a04e54d73b-use-json-builder-dsl-for-test-assertion-construction-tests-use-buildjsonobject.md @@ -0,0 +1,101 @@ +# Use JSON Builder DSL for Test Assertion Construction: Tests Use Buildjsonobject + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests require verification that domain objects correctly encode to JSON with specific structure and type discriminators +- The codebase uses kotlinx.serialization for JSON encoding/decoding with custom serializers for versioned state objects +- Test assertions need to compare expected JSON structure against actual serializer output without string-based comparison fragility +- The buildJsonObject DSL with put operations provides type-safe construction of expected JSON structures for assertion matching + +## Problem Statement + +Test assertions for JSON serialization require a reliable method to construct expected JSON structures that can be compared against actual serializer output. String-based JSON comparison is fragile and difficult to maintain, while manual JsonObject construction is verbose and error-prone. A standardized approach is needed to build expected JSON structures in tests that is both readable and type-safe. + +## Decision + +1. MAY: Tests MAY use buildJsonObject for constructing complex nested JSON structures when testing deep object hierarchies + +## Policy Block + +- MAY Tests MAY use buildJsonObject for constructing complex nested JSON structures when testing deep object hierarchies + +## Rationale + +- The pattern appears in 2 test files with 91.70% confidence, both using buildJsonObject with put operations for JSON assertion construction +- WrappedAccountCryptographicStateSerializerTest demonstrates the pattern for versioned state objects (V1, V2) with type discriminators +- VaultSdkPolicyExtensionsTest shows the pattern applied to SDK policy conversion testing with empty list and multi-item list scenarios +- The kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put functions provide the DSL foundation for this testing approach + +## Consequences + +Positive: +- Type-safe JSON construction in tests reduces runtime errors from malformed JSON strings +- DSL syntax improves test readability by making JSON structure explicit and self-documenting +- Refactoring serialization logic becomes safer as tests clearly express expected structure +- IDE support for DSL provides autocomplete and type checking during test development + +Negative: +- Developers must learn kotlinx.serialization DSL syntax in addition to standard assertion libraries +- Verbose buildJsonObject blocks may increase test code size compared to raw JSON strings +- Pattern creates coupling to kotlinx.serialization library for test infrastructure +- Complex nested JSON structures may become difficult to read despite DSL benefits + +## Alternatives + +- Use raw JSON strings with Json.parseToJsonElement for expected values (rejected) + Rejected because: String-based JSON is fragile, lacks type safety, and requires manual escaping of special characters + When valid: Acceptable for simple one-off tests where JSON structure is trivial and unlikely to change +- Construct JsonObject instances directly using JsonObject constructor (rejected) + Rejected because: Direct constructor usage is verbose and less readable than DSL syntax, reducing test maintainability + When valid: Valid when buildJsonObject DSL is unavailable or when programmatic construction is required +- Use snapshot testing to capture serialized JSON output (deferred) + Rejected because: Not rejected but deferred; snapshot testing complements rather than replaces structural assertions + When valid: Useful for regression testing of large JSON structures where exact structure verification is needed + +## Risks + +- DSL syntax changes in kotlinx.serialization updates could break existing tests + Mitigation: Pin kotlinx.serialization version and review release notes before upgrades; maintain test suite coverage + Owner: engineering team +- Overuse of buildJsonObject for simple assertions may reduce test clarity + Mitigation: Establish guidelines for when DSL is appropriate versus simpler assertion methods; code review enforcement + Owner: engineering team +- New team members unfamiliar with kotlinx.serialization DSL may write inconsistent tests + Mitigation: Document pattern in testing guidelines; provide examples in test templates; conduct code review training + Owner: engineering team + +## Implementation Notes + +- Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern +- Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order +- For versioned state objects, always verify the type discriminator field first in the buildJsonObject block +- Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests + +## Continuation Context + + +Verify commands: +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l +- grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' +- ./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' + +Accept when: +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output + +## Enforcement + +- Verified by: Code review checklist requiring buildJsonObject usage in serialization tests +- Verified by: Static analysis or linting rules detecting raw JSON strings in test assertions +- Verified by: CI pipeline test execution validating serialization test coverage +- Violation handling: Code review feedback requesting refactoring to buildJsonObject DSL +- Violation handling: Pull request comments with examples of correct pattern usage +- Violation handling: Test failures flagged for investigation if serialization assertions use non-standard approaches +- Exception process: Document rationale in test comments when alternative assertion method is necessary +- Exception process: Obtain approval from tech lead for exceptions in complex or legacy test scenarios +- Exception process: Track exceptions in testing guidelines document with justification and review date \ No newline at end of file diff --git a/docs/adr/c392ab05-f46c-43be-ac19-3bc5ce82c5e9-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md b/docs/adr/c392ab05-f46c-43be-ac19-3bc5ce82c5e9-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md new file mode 100644 index 00000000000..5fcb2d9594b --- /dev/null +++ b/docs/adr/c392ab05-f46c-43be-ac19-3bc5ce82c5e9-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-use-androidx.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Use Androidx + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. MAY: Activities MAY use androidx.activity.result.contract.ActivityResultContracts for type-safe activity result handling when coordinating with other activities or system pickers + +## Policy Block + +- MAY Activities MAY use androidx.activity.result.contract.ActivityResultContracts for type-safe activity result handling when coordinating with other activities or system pickers + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/c4e21335-6ee6-4833-9d24-9a8225827ff8-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-json.md b/docs/adr/c4e21335-6ee6-4833-9d24-9a8225827ff8-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-json.md new file mode 100644 index 00000000000..1eab663c27e --- /dev/null +++ b/docs/adr/c4e21335-6ee6-4833-9d24-9a8225827ff8-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-json.md @@ -0,0 +1,117 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Error Response Json + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Network error handling requires consistent testing patterns to validate error response parsing and exception mapping behavior +- The codebase uses custom exception types (CookieRedirectException, LocalNetworkAccessException) that must be converted to BitwardenError types with specific HTTP status codes +- OkHttp's Response.error() and ResponseBody.toResponseBody() provide a standard mechanism for creating mock HTTP error responses in unit tests +- JUnit 5 (@Test annotations) serves as the testing framework with assertion methods (assertEquals, assertTrue) for validating error transformation logic +- Error response bodies contain structured JSON with message and validationErrors fields that must be parsed and validated in test scenarios + +## Problem Statement + +Network layer error handling involves complex transformations between HTTP responses, custom exceptions, and domain error types. Without standardized testing patterns for error scenarios, teams may create inconsistent mock responses, fail to validate critical error parsing paths, or miss edge cases in exception-to-error mappings. This leads to fragile error handling code and potential runtime failures when unexpected HTTP error responses occur. + +## Decision + +1. SHOULD: Error response JSON in tests SHOULD include both message and validationErrors fields to validate complete parsing logic + +## Policy Block + +- SHOULD Error response JSON in tests SHOULD include both message and validationErrors fields to validate complete parsing logic + +In scope: +- Network layer unit tests in network/src/test/kotlin/**/*Test.kt +- Tests validating toBitwardenError() extension functions +- Tests validating parseErrorBodyOrNull() error parsing logic +- HTTP error response mocking for status codes 400-599 +- Custom exception type testing (CookieRedirectException, LocalNetworkAccessException) + +Out of scope: +- Integration tests with real HTTP clients +- End-to-end error handling flows +- UI layer error display testing +- Non-HTTP error scenarios (e.g., network timeouts, SSL errors) +- Production error logging implementation + +## Rationale + +- The evidence shows consistent use of Response.error() and toResponseBody() across 2 test files, indicating an established pattern for mocking HTTP error responses +- JUnit 5 assertions (assertEquals, assertTrue) provide type-safe validation of error transformations with clear failure messages +- Testing both exception-to-error mapping and JSON body parsing ensures comprehensive coverage of the error handling pipeline +- The pattern enables isolated unit testing of error logic without requiring actual network calls or HTTP server infrastructure + +## Consequences + +Positive: +- Consistent error response mocking reduces test code duplication and improves maintainability +- Type-safe assertions catch regressions in error transformation logic during refactoring +- Isolated unit tests execute quickly without network dependencies, enabling fast feedback loops +- Structured JSON validation ensures error messages and validation errors are correctly extracted for user display + +Negative: +- OkHttp-specific mocking creates tight coupling between tests and the HTTP client library +- Mock responses may diverge from actual server error formats if not kept synchronized +- Test coverage is limited to known error scenarios and may miss unexpected server responses +- Additional test code is required to maintain comprehensive error scenario coverage + +## Alternatives + +- Use MockWebServer to simulate full HTTP server responses for error testing (rejected) + Rejected because: MockWebServer adds complexity and slower test execution for unit-level error transformation logic that can be tested with simple mock objects + When valid: Integration tests requiring full request/response cycles with headers, redirects, and connection handling +- Create custom test fixtures or builders for BitwardenError instances (rejected) + Rejected because: Direct construction bypasses the actual transformation logic (toBitwardenError) that needs validation, reducing test coverage of production code paths + When valid: Tests focused on error handling behavior downstream of error creation, where the transformation itself is not under test +- Use property-based testing to generate random error responses (deferred) + Rejected because: Not currently implemented in the codebase; would require additional testing framework dependencies + When valid: Future enhancement to discover edge cases in error parsing logic with generated inputs + +## Risks + +- Mock error responses diverge from actual server API error formats over time + Mitigation: Maintain contract tests or API schema validation to ensure mock responses match production error formats; periodically review server API documentation + Owner: Network layer team +- OkHttp library updates may change Response.error() behavior or deprecate APIs + Mitigation: Pin OkHttp version in dependency management; review release notes during upgrades; maintain adapter layer if API changes + Owner: Engineering team +- Test coverage gaps for uncommon HTTP status codes or malformed response bodies + Mitigation: Use code coverage tools to identify untested error paths; add parameterized tests for status code ranges; include malformed JSON test cases + Owner: QA and development team + +## Implementation Notes + +- Import okhttp3.ResponseBody.Companion.toResponseBody and retrofit2.Response for creating mock error responses in test setup +- Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions +- Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability +- Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic) +- Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites + +## Continuation Context + + +Verify commands: +- grep -r "Response.error" network/src/test/kotlin/ | wc -l +- grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l +- grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l + +Accept when: +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields + +## Enforcement + +- Verified by: Code review checklist requiring error transformation tests for new exception types +- Verified by: CI pipeline test execution with minimum coverage thresholds for network error handling code +- Verified by: Static analysis to detect Response.error() usage patterns in test files +- Violation handling: Pull requests adding new error types without corresponding tests are blocked until tests are added +- Violation handling: Coverage drops in network error handling modules trigger build warnings and team notifications +- Violation handling: Quarterly audit of error test patterns identifies inconsistencies for remediation +- Exception process: Temporary exception granted for prototype or spike work with technical debt ticket created +- Exception process: Exception requires architecture team approval with documented rationale +- Exception process: All exceptions reviewed in monthly technical debt review meetings with remediation timeline \ No newline at end of file diff --git a/docs/adr/c6b2221d-a2a7-43d4-ac14-5a82f1353d03-enforce-input-validation-for-internal-api-configuration-parsers-internal-that-process.md b/docs/adr/c6b2221d-a2a7-43d4-ac14-5a82f1353d03-enforce-input-validation-for-internal-api-configuration-parsers-internal-that-process.md new file mode 100644 index 00000000000..894baa8f83d --- /dev/null +++ b/docs/adr/c6b2221d-a2a7-43d4-ac14-5a82f1353d03-enforce-input-validation-for-internal-api-configuration-parsers-internal-that-process.md @@ -0,0 +1,118 @@ +# Enforce Input Validation for Internal API Configuration Parsers: Internal That Process + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains internal API scripts that parse external configuration data using json.load and process command-line arguments via argparse +- Configuration-driven automation scripts interact with external systems (GitHub API via subprocess) and make decisions based on parsed JSON structures +- Input validation patterns are present in the form of dictionary key access with .get() methods and exception handling for json parsing errors +- The label-pr.py script demonstrates a pattern where untrusted input (PR titles, file paths, JSON configuration) flows through validation logic before triggering actions +- The pattern reflects a security-conscious approach to internal tooling where configuration parsing includes defensive programming practices + +## Problem Statement + +Internal API scripts that consume external configuration and interact with external systems require consistent input validation to prevent injection attacks, malformed data propagation, and runtime failures when processing untrusted or semi-trusted input sources. + +## Decision + +1. SHOULD: Internal APIs that process pattern matching (title_patterns, path_patterns) SHOULD validate pattern syntax before applying them to untrusted input + +## Policy Block + +- SHOULD Internal APIs that process pattern matching (title_patterns, path_patterns) SHOULD validate pattern syntax before applying them to untrusted input + +In scope: +- Python scripts in .github/scripts/ that parse JSON configuration +- Internal automation tools that interact with external APIs (GitHub, CI/CD systems) +- Configuration-driven label assignment and PR processing workflows +- Scripts that use argparse, json.load, or subprocess modules + +Out of scope: +- Public-facing API endpoints with dedicated web frameworks +- Database query parameter validation (covered by separate ORM/query builder policies) +- Frontend form validation logic +- Third-party library internal validation + +Exceptions: +- EXC-001: Prototype or proof-of-concept scripts in development branches that are not merged to main +- EXC-002: Scripts that only process configuration files maintained exclusively by the core team with no external input + +## Rationale + +- The evidence shows a consistent pattern of defensive programming in label-pr.py using .get() methods for dictionary access and exception handling for JSON parsing, indicating an established practice worth codifying +- Internal automation scripts often bridge trusted configuration with untrusted external input (PR titles, file paths), creating a security boundary that requires explicit validation +- The use of argparse demonstrates structured input handling that prevents common injection vulnerabilities compared to raw sys.argv parsing +- Codifying this pattern reduces the risk of security vulnerabilities in internal tooling that could be exploited to manipulate CI/CD pipelines or access control systems + +## Consequences + +Positive: +- Reduced risk of injection attacks and malformed data propagation in internal automation scripts +- Consistent error handling improves debuggability and reduces runtime failures in CI/CD pipelines +- Structured argument parsing with argparse provides built-in help documentation and type validation +- Defensive dictionary access patterns prevent KeyError exceptions and improve script resilience + +Negative: +- Additional validation code increases initial development time for internal scripts +- Exception handling and safe access patterns add modest runtime overhead +- May create false sense of security if validation is incomplete or bypassed in edge cases +- Requires ongoing developer education to maintain validation practices across the team + +## Alternatives + +- Use JSON Schema validation libraries (jsonschema, pydantic) for comprehensive configuration validation (deferred) + Rejected because: null + When valid: Consider for complex configuration structures with nested objects and strict type requirements; current evidence shows simpler validation patterns are sufficient for existing use cases +- Rely on implicit Python exception handling without explicit try-except blocks (rejected) + Rejected because: Implicit exception handling provides poor error messages and makes debugging difficult; the evidence shows explicit exception handling is already practiced + When valid: Never valid for production internal APIs +- Use direct sys.argv parsing instead of argparse (rejected) + Rejected because: Direct sys.argv parsing is error-prone, lacks built-in validation, and provides no automatic help documentation; argparse is already in use and provides superior developer experience + When valid: Only acceptable for trivial single-argument scripts with no validation requirements + +## Risks + +- Incomplete validation coverage may leave security gaps if developers only validate some input paths + Mitigation: Establish code review checklist for input validation; use static analysis tools to detect unvalidated input flows + Owner: Engineering team and security reviewers +- Validation logic may become outdated as configuration schemas evolve + Mitigation: Document configuration schema alongside validation code; include validation tests in CI pipeline + Owner: Script maintainers +- Overly strict validation may break existing workflows or prevent legitimate use cases + Mitigation: Implement validation incrementally with clear error messages; provide exception process for legitimate edge cases + Owner: Engineering team + +## Implementation Notes + +- Add try-except blocks around json.load() calls with specific exception handling for JSONDecodeError to provide clear error messages +- Replace direct dictionary key access (config['key']) with safe access patterns (config.get('key', default_value)) throughout internal scripts +- Use argparse.ArgumentParser for all command-line argument parsing with explicit type specifications and help text +- Document expected configuration schema in script docstrings or adjacent README files to guide validation implementation + +## Continuation Context + + +Verify commands: +- grep -r 'json\.load' .github/scripts/ | xargs -I {} sh -c 'grep -L "try:" $(echo {} | cut -d: -f1) && echo "Missing exception handling: {}"' +- grep -r '\["[^"]*"\]' .github/scripts/*.py | grep -v '\.get(' | head -5 +- find .github/scripts -name '*.py' -exec grep -l 'import argparse' {} \; | wc -l + +Accept when: +- All Python scripts that use json.load() include try-except blocks with JSONDecodeError or general exception handling +- Dictionary access in configuration parsing uses .get() methods or explicit 'key in dict' checks rather than direct bracket notation +- Scripts accepting command-line arguments use argparse or equivalent structured parsing libraries + +## Enforcement + +- Verified by: Code review checklist includes input validation verification for internal API scripts +- Verified by: Static analysis tools (pylint, bandit) configured to flag unsafe dictionary access and missing exception handling +- Verified by: CI pipeline includes grep-based validation checks for common input validation patterns +- Violation handling: Code review feedback requests addition of validation before approval +- Violation handling: CI warnings for detected validation gaps (non-blocking initially, blocking after grace period) +- Violation handling: Security review required for scripts that interact with external systems or process untrusted input +- Exception process: Developer documents the trust boundary and justification in PR description +- Exception process: Tech lead or security reviewer approves exception with explicit acknowledgment of risk +- Exception process: Exception is documented in script header comments with EXC-ID reference and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/c77883cd-f54d-461e-825b-f33537a65086-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-inject-multiple.md b/docs/adr/c77883cd-f54d-461e-825b-f33537a65086-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-inject-multiple.md new file mode 100644 index 00000000000..1bd0097aa89 --- /dev/null +++ b/docs/adr/c77883cd-f54d-461e-825b-f33537a65086-standardize-hiltviewmodel-for-android-viewmodel-dependency-injection-in-public-api-boundaries-viewmodels-inject-multiple.md @@ -0,0 +1,116 @@ +# Standardize HiltViewModel for Android ViewModel Dependency Injection in Public API Boundaries: Viewmodels Inject Multiple + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Three ViewModel implementations (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel) consistently use HiltViewModel annotation for dependency injection at public API boundaries handling Android Intent-based interactions +- All three ViewModels extend BaseViewModel and coordinate external API contracts through sealed action types (CredentialProviderAction, AuthCallbackAction) and data classes for Intent processing +- The pattern appears in ViewModels managing authentication flows, credential provider operations, and autofill callbacks, indicating a standardized approach to handling Android system integration points +- Dependencies injected include AuthRepository, BitwardenCredentialManager, and CredentialProviderRequestManager, suggesting a consistent architectural layer for external API coordination + +## Problem Statement + +Android ViewModels serving as public API boundaries for system integrations (credential providers, authentication callbacks, autofill) require consistent dependency injection to ensure testability, lifecycle management, and separation of concerns. Without a standardized DI approach, these critical integration points risk inconsistent initialization, difficult testing, and tight coupling to Android framework components. + +## Decision + +1. MAY: ViewModels MAY inject multiple repository or manager dependencies when coordinating complex external API workflows + +## Policy Block + +- MAY ViewModels MAY inject multiple repository or manager dependencies when coordinating complex external API workflows + +In scope: +- Android ViewModels handling credential provider APIs +- ViewModels processing authentication callback Intents +- ViewModels coordinating autofill service interactions +- Any ViewModel serving as boundary between Android system services and application logic + +Out of scope: +- Internal ViewModels not exposed to Android system APIs +- Fragment or Activity ViewModels handling only UI state +- Repository or manager layer components +- Non-Android platform integrations + +Exceptions: +- EXC-001: Legacy ViewModels predating Hilt adoption that require gradual migration + +## Rationale + +- Evidence shows 100% consistency across three distinct public API boundary ViewModels (credential provider, auth callback, autofill), indicating an established architectural pattern with 91.70% confidence +- HiltViewModel annotation provides Android-aware dependency injection that respects ViewModel lifecycle and survives configuration changes, critical for Intent-based system integrations +- Sealed action types and data classes create type-safe contracts that prevent runtime errors at public API boundaries where external systems interact with application logic +- Injected repository and manager components enable testability by allowing mock implementations during unit testing of Intent processing logic + +## Consequences + +Positive: +- Consistent dependency injection pattern across all public API boundary ViewModels improves maintainability and reduces cognitive load +- HiltViewModel lifecycle management prevents memory leaks and ensures proper cleanup of resources during configuration changes +- Testability improves through constructor injection, enabling unit tests with mock repositories without Android framework dependencies +- Type-safe sealed action contracts prevent runtime errors from malformed Intent data at system integration boundaries + +Negative: +- Introduces Hilt framework dependency for all public API ViewModels, increasing build complexity and annotation processing time +- Developers must understand Hilt scoping and lifecycle rules to correctly implement ViewModels at public API boundaries +- Migration of existing ViewModels to HiltViewModel pattern requires refactoring and testing effort +- Sealed action types increase boilerplate code compared to direct Intent parameter passing + +## Alternatives + +- Use manual ViewModel factory pattern with direct constructor injection (rejected) + Rejected because: Manual factory pattern requires boilerplate for each ViewModel and does not integrate with Android lifecycle-aware components as seamlessly as Hilt + When valid: In projects without Hilt or when minimizing annotation processing overhead is critical +- Use Dagger without Hilt for ViewModel injection (rejected) + Rejected because: Dagger alone requires more boilerplate and manual component management compared to Hilt's Android-specific optimizations + When valid: In projects with existing Dagger infrastructure where Hilt migration cost is prohibitive +- Use service locator pattern for dependency resolution in ViewModels (rejected) + Rejected because: Service locator pattern hides dependencies, reduces testability, and creates runtime dependency resolution failures instead of compile-time errors + When valid: Never recommended for new code; only acceptable in legacy codebases during gradual migration + +## Risks + +- Hilt annotation processing failures could break builds for all public API ViewModels simultaneously + Mitigation: Maintain Hilt version compatibility matrix, use Gradle dependency locking, and implement CI build verification for annotation processing + Owner: Engineering team +- Developers unfamiliar with Hilt may incorrectly scope dependencies, causing memory leaks or premature disposal + Mitigation: Provide ViewModel dependency injection guidelines, code review checklist, and automated lint rules to detect incorrect scoping + Owner: Architecture team +- Sealed action types may grow complex as public API contracts evolve, reducing maintainability + Mitigation: Establish action type design guidelines limiting nesting depth, use composition over inheritance, and refactor when action hierarchies exceed three levels + Owner: Engineering team + +## Implementation Notes + +- Annotate all public API boundary ViewModels with @HiltViewModel and ensure constructor parameters are annotated with @Inject +- Define sealed action types in companion objects or separate files to maintain clear contract boundaries between system APIs and application logic +- Use repository or manager layer components for Intent processing logic rather than embedding Android framework calls directly in ViewModel +- Implement unit tests for ViewModels using Hilt testing utilities (HiltAndroidTest) or manual constructor injection with mock dependencies + +## Continuation Context + + +Verify commands: +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | grep -E '(CredentialProvider|AuthCallback|Autofill)' | wc -l +- grep -r 'sealed.*Action' app/src/main/kotlin --include='*ViewModel.kt' -A 2 | grep -E '(CredentialProviderAction|AuthCallbackAction)' | wc -l +- find app/src/main/kotlin -name '*ViewModel.kt' -exec grep -l 'BaseViewModel' {} \; | xargs grep -l '@HiltViewModel' | wc -l + +Accept when: +- All ViewModels handling Intent-based public API interactions contain @HiltViewModel annotation +- Each public API ViewModel defines sealed action types for type-safe contract enforcement +- All public API ViewModels extend BaseViewModel and inject dependencies through constructor parameters + +## Enforcement + +- Verified by: Code review checklist requiring HiltViewModel annotation for all public API boundary ViewModels +- Verified by: Custom lint rule detecting ViewModels with Intent parameters lacking @HiltViewModel annotation +- Verified by: CI pipeline verification step running grep commands to validate pattern compliance +- Violation handling: CI build fails if public API ViewModels lack @HiltViewModel annotation +- Violation handling: Code review blocks merge if sealed action types are not used for Intent-based contracts +- Violation handling: Architecture team notified of violations for pattern compliance tracking +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in ADR exceptions registry with approval date and review schedule +- Exception process: Re-evaluate exception quarterly to assess migration feasibility \ No newline at end of file diff --git a/docs/adr/cc3efe3f-8dc4-4c51-99fb-c263092e61da-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-viewmodels-extend-baseviewmodel.md b/docs/adr/cc3efe3f-8dc4-4c51-99fb-c263092e61da-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-viewmodels-extend-baseviewmodel.md new file mode 100644 index 00000000000..0738dab3acd --- /dev/null +++ b/docs/adr/cc3efe3f-8dc4-4c51-99fb-c263092e61da-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-viewmodels-extend-baseviewmodel.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Viewmodels Extend Baseviewmodel + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. SHOULD: ViewModels SHOULD extend BaseViewModel and be annotated with @HiltViewModel to standardize state management and dependency injection patterns + +## Policy Block + +- SHOULD ViewModels SHOULD extend BaseViewModel and be annotated with @HiltViewModel to standardize state management and dependency injection patterns + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/cd9fb085-7d4d-4567-9f79-0b0dfc05be78-use-json-builder-dsl-for-test-assertion-construction-test-assertions-verifying.md b/docs/adr/cd9fb085-7d4d-4567-9f79-0b0dfc05be78-use-json-builder-dsl-for-test-assertion-construction-test-assertions-verifying.md new file mode 100644 index 00000000000..30826e5368b --- /dev/null +++ b/docs/adr/cd9fb085-7d4d-4567-9f79-0b0dfc05be78-use-json-builder-dsl-for-test-assertion-construction-test-assertions-verifying.md @@ -0,0 +1,101 @@ +# Use JSON Builder DSL for Test Assertion Construction: Test Assertions Verifying + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Serialization tests require verification that domain objects correctly encode to JSON with specific structure and type discriminators +- The codebase uses kotlinx.serialization for JSON encoding/decoding with custom serializers for versioned state objects +- Test assertions need to compare expected JSON structure against actual serializer output without string-based comparison fragility +- The buildJsonObject DSL with put operations provides type-safe construction of expected JSON structures for assertion matching + +## Problem Statement + +Test assertions for JSON serialization require a reliable method to construct expected JSON structures that can be compared against actual serializer output. String-based JSON comparison is fragile and difficult to maintain, while manual JsonObject construction is verbose and error-prone. A standardized approach is needed to build expected JSON structures in tests that is both readable and type-safe. + +## Decision + +1. MUST: Test assertions verifying JSON serialization output MUST use buildJsonObject DSL to construct expected JSON structures + +## Policy Block + +- MUST Test assertions verifying JSON serialization output MUST use buildJsonObject DSL to construct expected JSON structures + +## Rationale + +- The pattern appears in 2 test files with 91.70% confidence, both using buildJsonObject with put operations for JSON assertion construction +- WrappedAccountCryptographicStateSerializerTest demonstrates the pattern for versioned state objects (V1, V2) with type discriminators +- VaultSdkPolicyExtensionsTest shows the pattern applied to SDK policy conversion testing with empty list and multi-item list scenarios +- The kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put functions provide the DSL foundation for this testing approach + +## Consequences + +Positive: +- Type-safe JSON construction in tests reduces runtime errors from malformed JSON strings +- DSL syntax improves test readability by making JSON structure explicit and self-documenting +- Refactoring serialization logic becomes safer as tests clearly express expected structure +- IDE support for DSL provides autocomplete and type checking during test development + +Negative: +- Developers must learn kotlinx.serialization DSL syntax in addition to standard assertion libraries +- Verbose buildJsonObject blocks may increase test code size compared to raw JSON strings +- Pattern creates coupling to kotlinx.serialization library for test infrastructure +- Complex nested JSON structures may become difficult to read despite DSL benefits + +## Alternatives + +- Use raw JSON strings with Json.parseToJsonElement for expected values (rejected) + Rejected because: String-based JSON is fragile, lacks type safety, and requires manual escaping of special characters + When valid: Acceptable for simple one-off tests where JSON structure is trivial and unlikely to change +- Construct JsonObject instances directly using JsonObject constructor (rejected) + Rejected because: Direct constructor usage is verbose and less readable than DSL syntax, reducing test maintainability + When valid: Valid when buildJsonObject DSL is unavailable or when programmatic construction is required +- Use snapshot testing to capture serialized JSON output (deferred) + Rejected because: Not rejected but deferred; snapshot testing complements rather than replaces structural assertions + When valid: Useful for regression testing of large JSON structures where exact structure verification is needed + +## Risks + +- DSL syntax changes in kotlinx.serialization updates could break existing tests + Mitigation: Pin kotlinx.serialization version and review release notes before upgrades; maintain test suite coverage + Owner: engineering team +- Overuse of buildJsonObject for simple assertions may reduce test clarity + Mitigation: Establish guidelines for when DSL is appropriate versus simpler assertion methods; code review enforcement + Owner: engineering team +- New team members unfamiliar with kotlinx.serialization DSL may write inconsistent tests + Mitigation: Document pattern in testing guidelines; provide examples in test templates; conduct code review training + Owner: engineering team + +## Implementation Notes + +- Import kotlinx.serialization.json.buildJsonObject and kotlinx.serialization.json.put in test files using this pattern +- Structure buildJsonObject blocks with one put call per line for readability, matching the expected JSON key order +- For versioned state objects, always verify the type discriminator field first in the buildJsonObject block +- Use assertEquals with buildJsonObject as the expected value and json.encodeToJsonElement as the actual value for serialization tests + +## Continuation Context + + +Verify commands: +- grep -r 'buildJsonObject' app/src/test/kotlin --include='*Test.kt' | wc -l +- grep -r 'import kotlinx.serialization.json.buildJsonObject' app/src/test/kotlin --include='*Test.kt' +- ./gradlew test --tests '*SerializerTest' --tests '*ExtensionsTest' + +Accept when: +- All serialization test files use buildJsonObject DSL for expected JSON construction +- No raw JSON strings are used in assertEquals calls for serialization verification +- Test suite passes with buildJsonObject assertions matching json.encodeToJsonElement output + +## Enforcement + +- Verified by: Code review checklist requiring buildJsonObject usage in serialization tests +- Verified by: Static analysis or linting rules detecting raw JSON strings in test assertions +- Verified by: CI pipeline test execution validating serialization test coverage +- Violation handling: Code review feedback requesting refactoring to buildJsonObject DSL +- Violation handling: Pull request comments with examples of correct pattern usage +- Violation handling: Test failures flagged for investigation if serialization assertions use non-standard approaches +- Exception process: Document rationale in test comments when alternative assertion method is necessary +- Exception process: Obtain approval from tech lead for exceptions in complex or legacy test scenarios +- Exception process: Track exceptions in testing guidelines document with justification and review date \ No newline at end of file diff --git a/docs/adr/ceec2cd4-0327-4e63-817b-921b9a4415da-adopt-model-context-protocol-sdk-for-android-device-integration-tool-implementations-modularized.md b/docs/adr/ceec2cd4-0327-4e63-817b-921b9a4415da-adopt-model-context-protocol-sdk-for-android-device-integration-tool-implementations-modularized.md new file mode 100644 index 00000000000..4b56052334d --- /dev/null +++ b/docs/adr/ceec2cd4-0327-4e63-817b-921b9a4415da-adopt-model-context-protocol-sdk-for-android-device-integration-tool-implementations-modularized.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Tool Implementations Modularized + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. SHOULD: Tool implementations SHOULD be modularized by capability domain (e.g., ./tools/capture.js) + +## Policy Block + +- SHOULD Tool implementations SHOULD be modularized by capability domain (e.g., ./tools/capture.js) + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/cf91fbd7-c73a-4797-aee1-f3d03d7995d0-adopt-async-handler-pattern-for-tool-operations-tool-implementations-export.md b/docs/adr/cf91fbd7-c73a-4797-aee1-f3d03d7995d0-adopt-async-handler-pattern-for-tool-operations-tool-implementations-export.md new file mode 100644 index 00000000000..9d160cbeb0f --- /dev/null +++ b/docs/adr/cf91fbd7-c73a-4797-aee1-f3d03d7995d0-adopt-async-handler-pattern-for-tool-operations-tool-implementations-export.md @@ -0,0 +1,120 @@ +# Adopt Async Handler Pattern for Tool Operations: Tool Implementations Export + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the android-device-server MCP service. + +## Context + +- The android-device-server MCP service implements multiple tool operations (capture, tap-at, find-element-pipeline) that interact with external Android Debug Bridge (adb) processes and file system operations +- Tool operations require coordination of asynchronous I/O including process execution, file reads/writes, and validation steps that cannot block the event loop +- Each tool exports a handler function that serves as the primary entry point for tool invocation, establishing a consistent interface pattern across the codebase +- The codebase uses Zod for input validation schemas and node:path/node:fs for file system operations, requiring async coordination between validation and execution phases + +## Problem Statement + +Tool operations in the android-device-server require a consistent concurrency model that coordinates asynchronous validation, external process execution, and file system operations without blocking the Node.js event loop, while maintaining a uniform interface pattern across all tool implementations. + +## Decision + +1. MUST: Tool implementations MUST export an async handler function as the primary entry point for tool operations + +## Policy Block + +- MUST Tool implementations MUST export an async handler function as the primary entry point for tool operations + +In scope: +- All tool implementations in the android-device-server/src/tools directory +- Handler functions that coordinate adb process execution +- Operations involving file system reads/writes via node:fs +- Tool entry points exported for MCP service consumption + +Out of scope: +- Utility functions that do not serve as tool entry points +- Synchronous helper functions for data transformation +- Type definitions and interface declarations +- Test harness and mock implementations + +Exceptions: +- EXC-001: Pure computational functions that perform synchronous transformations without I/O + +## Rationale + +- The evidence shows consistent use of async handler functions (capture, tapAt, findElementWithObstruction) across 3 tool implementations, indicating an established pattern for coordinating asynchronous operations +- All detected tools import adb utilities and validation modules, requiring async coordination between validation, process execution, and result handling +- The handler pattern provides a uniform interface for tool invocation while encapsulating the complexity of async I/O coordination with external processes and file systems +- Using async/await patterns prevents event loop blocking and enables proper error propagation in the Node.js runtime environment + +## Consequences + +Positive: +- Consistent interface pattern across all tool implementations improves code maintainability and developer onboarding +- Non-blocking async operations ensure the MCP service remains responsive during long-running adb operations +- Separation of validation and execution phases enables early input rejection before expensive I/O operations +- Async/await syntax provides clear error handling and control flow compared to callback-based patterns + +Negative: +- Async handler pattern adds complexity compared to synchronous implementations for simple operations +- Requires developers to understand Promise semantics and async/await error handling +- Potential for unhandled promise rejections if error handling is not properly implemented +- Debugging async call stacks can be more challenging than synchronous execution flows + +## Alternatives + +- Synchronous handler functions with blocking I/O operations (rejected) + Rejected because: Blocking I/O would freeze the Node.js event loop during adb process execution and file operations, making the service unresponsive to concurrent requests + When valid: Only appropriate for pure computational functions without I/O dependencies +- Callback-based asynchronous pattern using Node.js callback conventions (rejected) + Rejected because: Callback patterns lead to nested callback hell and more complex error handling compared to async/await syntax available in modern Node.js + When valid: Legacy codebases or when targeting very old Node.js versions without async/await support +- Event emitter pattern for tool operations (rejected) + Rejected because: Event emitters add unnecessary complexity for request-response tool operations that have clear start and end points + When valid: Appropriate for streaming operations or long-running processes with multiple intermediate events + +## Risks + +- Unhandled promise rejections in handler functions could crash the Node.js process or leave operations in inconsistent states + Mitigation: Implement comprehensive try-catch blocks in all async handlers and configure Node.js to log unhandled rejections. Add integration tests that verify error handling paths. + Owner: Engineering team +- Long-running adb operations could accumulate pending promises and exhaust memory if not properly managed + Mitigation: Implement timeouts for all adb operations and add monitoring for pending promise counts. Consider implementing operation queuing with concurrency limits. + Owner: Engineering team +- Inconsistent error handling patterns across handlers could lead to unpredictable failure modes + Mitigation: Establish standard error handling patterns and document them. Create shared error handling utilities that all handlers can use. + Owner: Engineering team + +## Implementation Notes + +- All new tool implementations should follow the pattern: export an async function that accepts validated parameters and returns a Promise of the operation result +- Use Zod schemas defined at module level for input validation, and validate before entering the async handler logic +- Import adb utilities and file system operations from their respective modules (../adb/adb.js, node:fs, node:path) and await their results +- Ensure all async handlers have proper error handling with try-catch blocks and meaningful error messages that include context about the failed operation + +## Continuation Context + + +Verify commands: +- grep -r 'export.*async.*function' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'await.*adb\.' .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r 'z\.object({' .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool files in src/tools/ export at least one async handler function +- All handlers that call adb operations use await for process coordination +- All tool modules define Zod validation schemas for input parameters + +## Enforcement + +- Verified by: Code review checklist requiring async handler pattern for new tools +- Verified by: ESLint rules detecting synchronous I/O operations in tool handlers +- Verified by: Integration tests verifying non-blocking behavior under concurrent load +- Violation handling: Code review rejection for synchronous I/O in handler functions +- Violation handling: CI pipeline failure on ESLint violations for blocking operations +- Violation handling: Automated comments on PRs identifying missing async/await patterns +- Exception process: Document exception rationale in ADR amendment or inline code comments +- Exception process: Obtain tech lead approval for synchronous operations in tool handlers +- Exception process: Add exception to ESLint configuration with justification comment \ No newline at end of file diff --git a/docs/adr/cfac6e70-958b-4189-8289-9daed54c616a-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-tests-use.md b/docs/adr/cfac6e70-958b-4189-8289-9daed54c616a-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-tests-use.md new file mode 100644 index 00000000000..5ceb3dce571 --- /dev/null +++ b/docs/adr/cfac6e70-958b-4189-8289-9daed54c616a-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-tests-use.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Python Tests Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. MUST: Python tests MUST use unittest assertion methods (assertTrue, assertFalse, assertEqual, assertIn) rather than plain assert statements + +## Policy Block + +- MUST Python tests MUST use unittest assertion methods (assertTrue, assertFalse, assertEqual, assertIn) rather than plain assert statements + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/d0fc711e-daaf-43ac-8555-b20545adec9a-adopt-model-context-protocol-sdk-for-real-time-device-integration-error-handling-distinguish.md b/docs/adr/d0fc711e-daaf-43ac-8555-b20545adec9a-adopt-model-context-protocol-sdk-for-real-time-device-integration-error-handling-distinguish.md new file mode 100644 index 00000000000..4a8b2f9b8d0 --- /dev/null +++ b/docs/adr/d0fc711e-daaf-43ac-8555-b20545adec9a-adopt-model-context-protocol-sdk-for-real-time-device-integration-error-handling-distinguish.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Error Handling Distinguish + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. MUST: Error handling MUST distinguish between tool-level errors (logged with tool context) and fatal server errors (logged as fatal) + +## Policy Block + +- MUST Error handling MUST distinguish between tool-level errors (logged with tool context) and fatal server errors (logged as fatal) + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/d158cb0f-6daf-4b88-89e4-957f2b1b8826-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-classes-organize.md b/docs/adr/d158cb0f-6daf-4b88-89e4-957f2b1b8826-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-classes-organize.md new file mode 100644 index 00000000000..70c0e65496c --- /dev/null +++ b/docs/adr/d158cb0f-6daf-4b88-89e4-957f2b1b8826-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-test-classes-organize.md @@ -0,0 +1,117 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Test Classes Organize + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Network error handling requires consistent testing patterns to validate error response parsing and exception mapping behavior +- The codebase uses custom exception types (CookieRedirectException, LocalNetworkAccessException) that must be converted to BitwardenError types with specific HTTP status codes +- OkHttp's Response.error() and ResponseBody.toResponseBody() provide a standard mechanism for creating mock HTTP error responses in unit tests +- JUnit 5 (@Test annotations) serves as the testing framework with assertion methods (assertEquals, assertTrue) for validating error transformation logic +- Error response bodies contain structured JSON with message and validationErrors fields that must be parsed and validated in test scenarios + +## Problem Statement + +Network layer error handling involves complex transformations between HTTP responses, custom exceptions, and domain error types. Without standardized testing patterns for error scenarios, teams may create inconsistent mock responses, fail to validate critical error parsing paths, or miss edge cases in exception-to-error mappings. This leads to fragile error handling code and potential runtime failures when unexpected HTTP error responses occur. + +## Decision + +1. MAY: Test classes MAY organize error handling tests by exception type (e.g., BitwardenErrorTest, ExceptionExtensionsTest) for clarity + +## Policy Block + +- MAY Test classes MAY organize error handling tests by exception type (e.g., BitwardenErrorTest, ExceptionExtensionsTest) for clarity + +In scope: +- Network layer unit tests in network/src/test/kotlin/**/*Test.kt +- Tests validating toBitwardenError() extension functions +- Tests validating parseErrorBodyOrNull() error parsing logic +- HTTP error response mocking for status codes 400-599 +- Custom exception type testing (CookieRedirectException, LocalNetworkAccessException) + +Out of scope: +- Integration tests with real HTTP clients +- End-to-end error handling flows +- UI layer error display testing +- Non-HTTP error scenarios (e.g., network timeouts, SSL errors) +- Production error logging implementation + +## Rationale + +- The evidence shows consistent use of Response.error() and toResponseBody() across 2 test files, indicating an established pattern for mocking HTTP error responses +- JUnit 5 assertions (assertEquals, assertTrue) provide type-safe validation of error transformations with clear failure messages +- Testing both exception-to-error mapping and JSON body parsing ensures comprehensive coverage of the error handling pipeline +- The pattern enables isolated unit testing of error logic without requiring actual network calls or HTTP server infrastructure + +## Consequences + +Positive: +- Consistent error response mocking reduces test code duplication and improves maintainability +- Type-safe assertions catch regressions in error transformation logic during refactoring +- Isolated unit tests execute quickly without network dependencies, enabling fast feedback loops +- Structured JSON validation ensures error messages and validation errors are correctly extracted for user display + +Negative: +- OkHttp-specific mocking creates tight coupling between tests and the HTTP client library +- Mock responses may diverge from actual server error formats if not kept synchronized +- Test coverage is limited to known error scenarios and may miss unexpected server responses +- Additional test code is required to maintain comprehensive error scenario coverage + +## Alternatives + +- Use MockWebServer to simulate full HTTP server responses for error testing (rejected) + Rejected because: MockWebServer adds complexity and slower test execution for unit-level error transformation logic that can be tested with simple mock objects + When valid: Integration tests requiring full request/response cycles with headers, redirects, and connection handling +- Create custom test fixtures or builders for BitwardenError instances (rejected) + Rejected because: Direct construction bypasses the actual transformation logic (toBitwardenError) that needs validation, reducing test coverage of production code paths + When valid: Tests focused on error handling behavior downstream of error creation, where the transformation itself is not under test +- Use property-based testing to generate random error responses (deferred) + Rejected because: Not currently implemented in the codebase; would require additional testing framework dependencies + When valid: Future enhancement to discover edge cases in error parsing logic with generated inputs + +## Risks + +- Mock error responses diverge from actual server API error formats over time + Mitigation: Maintain contract tests or API schema validation to ensure mock responses match production error formats; periodically review server API documentation + Owner: Network layer team +- OkHttp library updates may change Response.error() behavior or deprecate APIs + Mitigation: Pin OkHttp version in dependency management; review release notes during upgrades; maintain adapter layer if API changes + Owner: Engineering team +- Test coverage gaps for uncommon HTTP status codes or malformed response bodies + Mitigation: Use code coverage tools to identify untested error paths; add parameterized tests for status code ranges; include malformed JSON test cases + Owner: QA and development team + +## Implementation Notes + +- Import okhttp3.ResponseBody.Companion.toResponseBody and retrofit2.Response for creating mock error responses in test setup +- Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions +- Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability +- Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic) +- Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites + +## Continuation Context + + +Verify commands: +- grep -r "Response.error" network/src/test/kotlin/ | wc -l +- grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l +- grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l + +Accept when: +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields + +## Enforcement + +- Verified by: Code review checklist requiring error transformation tests for new exception types +- Verified by: CI pipeline test execution with minimum coverage thresholds for network error handling code +- Verified by: Static analysis to detect Response.error() usage patterns in test files +- Violation handling: Pull requests adding new error types without corresponding tests are blocked until tests are added +- Violation handling: Coverage drops in network error handling modules trigger build warnings and team notifications +- Violation handling: Quarterly audit of error test patterns identifies inconsistencies for remediation +- Exception process: Temporary exception granted for prototype or spike work with technical debt ticket created +- Exception process: Exception requires architecture team approval with documented rationale +- Exception process: All exceptions reviewed in monthly technical debt review meetings with remediation timeline \ No newline at end of file diff --git a/docs/adr/d6b5a93c-a86e-48b5-ab0f-e66269b640ad-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-modules.md b/docs/adr/d6b5a93c-a86e-48b5-ab0f-e66269b640ad-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-modules.md new file mode 100644 index 00000000000..25dd1f67661 --- /dev/null +++ b/docs/adr/d6b5a93c-a86e-48b5-ab0f-e66269b640ad-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-modules.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Typescript Test Modules + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. MUST: TypeScript test modules MUST use vitest with describe/it block structure for test organization + +## Policy Block + +- MUST TypeScript test modules MUST use vitest with describe/it block structure for test organization + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/d89870be-79f5-4b57-9124-0ebfa63ccf07-adopt-model-context-protocol-sdk-for-real-time-device-integration-real-time-integration.md b/docs/adr/d89870be-79f5-4b57-9124-0ebfa63ccf07-adopt-model-context-protocol-sdk-for-real-time-device-integration-real-time-integration.md new file mode 100644 index 00000000000..58b7a981f80 --- /dev/null +++ b/docs/adr/d89870be-79f5-4b57-9124-0ebfa63ccf07-adopt-model-context-protocol-sdk-for-real-time-device-integration-real-time-integration.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Real Time Integration + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. MUST: Real-time integration servers MUST use the Model Context Protocol SDK (@modelcontextprotocol/sdk/server/index.js) as the foundation for server implementation + +## Policy Block + +- MUST Real-time integration servers MUST use the Model Context Protocol SDK (@modelcontextprotocol/sdk/server/index.js) as the foundation for server implementation + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/dbb825c6-c6c7-4a92-8d5a-239b88eff0bb-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-implementations-extend-error.md b/docs/adr/dbb825c6-c6c7-4a92-8d5a-239b88eff0bb-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-implementations-extend-error.md new file mode 100644 index 00000000000..002787c34bc --- /dev/null +++ b/docs/adr/dbb825c6-c6c7-4a92-8d5a-239b88eff0bb-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-implementations-extend-error.md @@ -0,0 +1,114 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Implementations Extend Error + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-mcp server implementation requires structured error reporting for tool execution failures and fatal errors +- The @modelcontextprotocol/sdk provides server infrastructure including server/index.js, server/stdio.js, and types.js modules for building MCP-compliant servers +- Console-based error logging is used for both tool-level errors (with tool name context) and fatal server errors +- The server operates in a real-time boundary context with tool discovery patterns using array find operations +- Error visibility is critical for debugging tool execution failures in the MCP server environment + +## Problem Statement + +MCP server implementations need consistent error logging that captures both tool-specific failures and fatal server errors while maintaining compatibility with the @modelcontextprotocol/sdk framework and stdio-based communication patterns. + +## Decision + +1. MAY: Implementations MAY extend error logging with additional context fields beyond name and message + +## Policy Block + +- MAY Implementations MAY extend error logging with additional context fields beyond name and message + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within MCP servers +- Fatal error reporting in server lifecycle +- stdio-based MCP server communication + +Out of scope: +- Client-side MCP implementations +- Structured logging frameworks (e.g., Winston, Bunyan) +- Application-level business logic logging +- Performance metrics or tracing + +## Rationale + +- The evidence shows consistent use of console.error for both tool-level and fatal errors, establishing a pattern for error visibility in MCP server contexts +- The @modelcontextprotocol/sdk provides the foundational server infrastructure, making it a core dependency for MCP server implementations +- Console-based logging aligns with stdio-based server communication patterns where structured logging frameworks might interfere with the protocol +- The pattern of including tool names in error messages provides essential context for debugging in a tool-discovery architecture + +## Consequences + +Positive: +- Simple, dependency-free error logging that works immediately without configuration +- Compatible with stdio-based MCP protocol communication without interference +- Clear error context through structured message formats including tool names +- Minimal overhead for error reporting in real-time server operations + +Negative: +- Console.error lacks structured logging capabilities (no log levels, filtering, or formatting) +- No built-in log aggregation or persistence mechanisms +- Limited observability compared to dedicated logging frameworks +- Difficult to implement log sampling or rate limiting for high-frequency errors + +## Alternatives + +- Use a structured logging framework like Winston or Pino (rejected) + Rejected because: Structured logging frameworks may interfere with stdio-based MCP protocol communication and add unnecessary dependencies for simple error reporting + When valid: When MCP servers require log aggregation, filtering, or integration with centralized logging systems +- Implement custom error handling without console output (rejected) + Rejected because: Silent error handling would eliminate visibility into tool failures and fatal errors, making debugging impossible + When valid: Never valid for server implementations requiring operational visibility +- Use process.stderr.write for direct stream writing (rejected) + Rejected because: Direct stream writing requires manual formatting and lacks the convenience of console.error while providing minimal benefit + When valid: When precise control over stderr buffering or formatting is required + +## Risks + +- Console.error output may interfere with MCP protocol messages on stdio if not properly separated + Mitigation: Ensure stderr is used for errors (console.error) while stdout is reserved for protocol messages + Owner: engineering team +- Lack of log levels makes it difficult to filter or prioritize errors in production + Mitigation: Use consistent message prefixes ('Tool error', 'Fatal error') to enable grep-based filtering + Owner: engineering team +- No log persistence means errors are lost if not captured by process supervisor + Mitigation: Deploy MCP servers with process managers that capture stderr (systemd, PM2, Docker logging) + Owner: operations team + +## Implementation Notes + +- Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities +- Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}' +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) +- Ensure the server uses stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr) + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +Accept when: +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure + +## Enforcement + +- Verified by: Code review checking for console.error usage patterns +- Verified by: Grep-based verification commands in CI pipeline +- Verified by: Runtime testing of error scenarios to verify stderr output +- Violation handling: Code review feedback requesting correction to standard error logging format +- Violation handling: CI pipeline warnings for missing or non-standard error logging +- Violation handling: Documentation updates to clarify error logging requirements +- Exception process: Request exception through architecture review for alternative logging approaches +- Exception process: Document rationale for deviation including technical constraints +- Exception process: Obtain approval from platform team before implementing alternative logging \ No newline at end of file diff --git a/docs/adr/dbef69a5-6060-40bb-a8cd-ec32d52b7119-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-files.md b/docs/adr/dbef69a5-6060-40bb-a8cd-ec32d52b7119-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-files.md new file mode 100644 index 00000000000..0b1723ca081 --- /dev/null +++ b/docs/adr/dbef69a5-6060-40bb-a8cd-ec32d52b7119-adopt-unittest-and-vitest-as-standard-testing-frameworks-typescript-test-files.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Typescript Test Files + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. MUST: TypeScript test files MUST use the *.spec.ts naming convention + +## Policy Block + +- MUST TypeScript test files MUST use the *.spec.ts naming convention + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/dbfa248c-cae8-4b7a-86a3-b5500a8e6cee-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-components-separate.md b/docs/adr/dbfa248c-cae8-4b7a-86a3-b5500a8e6cee-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-components-separate.md new file mode 100644 index 00000000000..93bc2167552 --- /dev/null +++ b/docs/adr/dbfa248c-cae8-4b7a-86a3-b5500a8e6cee-adopt-model-context-protocol-sdk-for-real-time-device-integration-integration-components-separate.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Real-Time Device Integration: Integration Components Separate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all integration components that establish real-time communication boundaries with external devices or services. + +## Context + +- The android-device-mcp server requires bidirectional real-time communication with Android devices through a standardized protocol interface +- The Model Context Protocol SDK (@modelcontextprotocol/sdk) provides server capabilities, stdio transport, and type definitions for tool-based integrations +- Tool discovery and invocation patterns require runtime lookup mechanisms (tools.find) to match requested tool names with registered handlers +- Error handling and logging boundaries separate tool-level errors from fatal server errors, enabling graceful degradation +- The server declares capabilities upfront ({ capabilities: { tools: {} } }) to establish the integration contract with clients + +## Problem Statement + +Integration components that communicate with external devices or services need a standardized protocol framework that supports real-time bidirectional communication, tool registration and discovery, structured error handling, and capability negotiation without requiring custom protocol implementation for each integration point. + +## Decision + +1. MAY: Integration components MAY separate validation logic (./utils/validation.js) and tool implementations (./tools/capture.js) into dedicated modules + +## Policy Block + +- MAY Integration components MAY separate validation logic (./utils/validation.js) and tool implementations (./tools/capture.js) into dedicated modules + +In scope: +- Real-time device integration servers (e.g., android-device-mcp) +- Tool-based integration components that expose capabilities to external clients +- Bidirectional communication boundaries requiring protocol standardization +- Integration points that require capability negotiation and discovery + +Out of scope: +- Unidirectional data pipelines or batch processing integrations +- REST API endpoints without real-time requirements +- Internal service-to-service communication within the same runtime +- Legacy integrations with established custom protocols + +Exceptions: +- EXC-001: The integration target does not support stdio transport and requires alternative transport mechanisms (WebSocket, HTTP SSE) +- EXC-002: Performance profiling demonstrates that MCP SDK overhead exceeds 10% of total request latency for high-throughput integrations + +## Rationale + +- The evidence shows explicit imports of @modelcontextprotocol/sdk components (server/index.js, server/stdio.js, types.js), indicating deliberate adoption of a standardized protocol framework rather than custom implementation +- The server initialization pattern (new Server with name, version, and capabilities) establishes a contract-first approach to integration, enabling clients to discover available functionality before invocation +- Runtime tool lookup (tools.find(t => t.name === name)) demonstrates dynamic dispatch requirements that benefit from protocol-level standardization rather than hardcoded routing +- Separation of tool-level errors from fatal errors in the logging evidence indicates architectural boundaries that align with the MCP SDK's error handling model + +## Consequences + +Positive: +- Standardized protocol reduces integration complexity and eliminates custom protocol implementation for each device or service boundary +- Capability declaration enables clients to discover available tools and features without out-of-band documentation or trial-and-error +- Structured error handling boundaries improve debuggability by separating tool failures from server infrastructure failures +- Type definitions from the SDK provide compile-time safety and reduce protocol compliance errors + +Negative: +- Dependency on @modelcontextprotocol/sdk introduces external package maintenance burden and potential breaking changes +- Protocol overhead may impact latency for high-frequency, low-latency integration scenarios +- Stdio transport assumption may require adaptation layers for integrations that need alternative transport mechanisms +- Learning curve for teams unfamiliar with Model Context Protocol conventions and patterns + +## Alternatives + +- Implement custom JSON-RPC protocol over stdio without SDK dependency (rejected) + Rejected because: Custom protocol implementation increases maintenance burden, lacks standardized capability negotiation, and requires clients to implement protocol-specific logic for each integration + When valid: Valid for integrations with extreme performance requirements where SDK overhead is measured and unacceptable +- Use gRPC with protocol buffers for device communication (rejected) + Rejected because: gRPC requires more complex infrastructure (HTTP/2, protobuf compilation), lacks the tool-oriented capability model, and introduces heavier runtime dependencies + When valid: Valid for high-throughput streaming scenarios or when integrating with existing gRPC-based ecosystems +- Adopt GraphQL subscriptions for real-time device queries (rejected) + Rejected because: GraphQL is query-oriented rather than tool/action-oriented, requires schema definition overhead, and lacks the stdio transport simplicity for process-based integrations + When valid: Valid when integration clients primarily need flexible data querying rather than tool invocation + +## Risks + +- Model Context Protocol SDK may introduce breaking changes in future versions, requiring integration rewrites + Mitigation: Pin SDK version in package.json, establish automated integration tests, monitor SDK release notes, and budget time for migration testing before upgrading + Owner: Integration team +- Stdio transport may not scale to high-concurrency scenarios with multiple simultaneous device connections + Mitigation: Implement connection pooling, measure concurrent connection limits in load testing, and document transport adaptation points for future scaling needs + Owner: Performance engineering team +- Tool lookup using runtime search (tools.find) may become a performance bottleneck as tool count grows + Mitigation: Profile tool lookup latency, consider migrating to Map-based lookup if tool count exceeds 50, and implement caching for frequently accessed tools + Owner: Engineering team + +## Implementation Notes + +- Initialize the MCP server with explicit name and version metadata to enable client identification and version negotiation +- Declare all capabilities upfront in the server constructor to establish the integration contract before handling requests +- Organize tool implementations in separate modules (e.g., ./tools/capture.js) and maintain a registry for runtime lookup +- Implement validation utilities (e.g., ./utils/validation.js) to verify tool parameters before execution and provide clear error messages +- Use console.error with contextual prefixes ('Tool error', 'Fatal error') to distinguish error severity levels in logs + +## Continuation Context + + +Verify commands: +- grep -r '@modelcontextprotocol/sdk' --include='*.ts' --include='*.js' | grep -E '(server/index|server/stdio|types)' | wc -l +- grep -r 'new Server' --include='*.ts' --include='*.js' -A 3 | grep 'capabilities:' | wc -l +- grep -r '\.find.*=>.*\.name ===' --include='*.ts' --include='*.js' | wc -l + +Accept when: +- All integration server implementations import at least one @modelcontextprotocol/sdk module (server, stdio, or types) +- Server initialization includes capabilities declaration with at least one capability key +- Tool lookup or dispatch logic uses collection search patterns to resolve names to handlers + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk imports in integration server files +- Verified by: Code review checklist requiring capabilities declaration in server initialization +- Verified by: Integration tests verifying tool discovery and invocation through MCP protocol +- Violation handling: CI pipeline fails if integration servers lack MCP SDK imports or capabilities declaration +- Violation handling: Code review blocks merge if tool lookup patterns bypass protocol-standard discovery mechanisms +- Violation handling: Architecture review required for any custom protocol implementation in real-time integration boundaries +- Exception process: Submit exception request with performance benchmarks or technical constraints documentation +- Exception process: Architecture review board evaluates alternative protocol justification +- Exception process: Approved exceptions require documented protocol compliance verification and migration path \ No newline at end of file diff --git a/docs/adr/dcfc1578-9eef-45ea-aaab-245004231943-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-github-interactions-encapsulated.md b/docs/adr/dcfc1578-9eef-45ea-aaab-245004231943-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-github-interactions-encapsulated.md new file mode 100644 index 00000000000..554af6e108b --- /dev/null +++ b/docs/adr/dcfc1578-9eef-45ea-aaab-245004231943-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-github-interactions-encapsulated.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Github Interactions Encapsulated + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. MUST: GitHub API interactions MUST be encapsulated in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) to isolate external client boundaries + +## Policy Block + +- MUST GitHub API interactions MUST be encapsulated in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) to isolate external client boundaries + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/dd22b744-04ad-4bef-826b-11857803deae-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-xml-parsing-operations.md b/docs/adr/dd22b744-04ad-4bef-826b-11857803deae-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-xml-parsing-operations.md new file mode 100644 index 00000000000..78acc99bbcb --- /dev/null +++ b/docs/adr/dd22b744-04ad-4bef-826b-11857803deae-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-xml-parsing-operations.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Xml Parsing Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. MUST: XML parsing operations MUST use fast-xml-parser with parser.parse() to validate structure before extracting UI hierarchy or element data + +## Policy Block + +- MUST XML parsing operations MUST use fast-xml-parser with parser.parse() to validate structure before extracting UI hierarchy or element data + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/ddfe2b69-49cf-4137-a3cf-95ba2ba77b05-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-handling-system.md b/docs/adr/ddfe2b69-49cf-4137-a3cf-95ba2ba77b05-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-handling-system.md new file mode 100644 index 00000000000..06430025b04 --- /dev/null +++ b/docs/adr/ddfe2b69-49cf-4137-a3cf-95ba2ba77b05-adopt-android-activity-and-androidx-componentactivity-as-application-entry-points-activities-handling-system.md @@ -0,0 +1,125 @@ +# Adopt Android Activity and AndroidX ComponentActivity as Application Entry Points: Activities Handling System + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The application requires multiple entry points for different Android system interactions including credential provider flows, OAuth callbacks, autofill callbacks, and main application UI +- Android platform requires Activity subclasses to handle lifecycle events, Intent routing, and system integration points such as ComponentCaller and Bundle state management +- AndroidX libraries provide ComponentActivity and AppCompatActivity as modern base classes that integrate with Jetpack components including ViewModel, Compose, and activity result contracts +- The application uses dependency injection (AndroidEntryPoint, HiltViewModel) requiring framework-aware Activity implementations that support Hilt's code generation and injection lifecycle +- Eight Activity and ViewModel implementations demonstrate consistent patterns of Intent handling, lifecycle management, and integration with androidx.activity.viewModels and androidx.lifecycle.viewModelScope + +## Problem Statement + +Android applications require structured entry points that integrate with platform lifecycle management, Intent routing, state preservation, and dependency injection while supporting modern Jetpack components including ViewModel, Compose, and activity result contracts across multiple specialized flows such as credential provisioning, authentication callbacks, and autofill services. + +## Decision + +1. SHOULD: Activities handling system callbacks SHOULD implement specialized flows for credential provider (CredentialProviderActivity), authentication (AuthCallbackActivity), and autofill (AutofillCallbackActivity) to maintain separation of concerns + +## Policy Block + +- SHOULD Activities handling system callbacks SHOULD implement specialized flows for credential provider (CredentialProviderActivity), authentication (AuthCallbackActivity), and autofill (AutofillCallbackActivity) to maintain separation of concerns + +In scope: +- All Activity subclasses serving as application entry points +- ViewModel implementations paired with Activities for state management +- Application class initialization (BitwardenApplication) +- System integration points including credential provider, OAuth callbacks, and autofill services + +Out of scope: +- Fragment implementations and their lifecycle management +- Service components and background processing +- BroadcastReceiver implementations +- ContentProvider implementations +- Compose-only UI components without Activity context + +Exceptions: +- EXC-001: Legacy Activity implementations may temporarily use android.app.Activity base class during migration to AndroidX + +## Rationale + +- Evidence shows 8 files consistently using androidx.activity.ComponentActivity and androidx.appcompat.app.AppCompatActivity as base classes, demonstrating established architectural pattern with 92.20% confidence +- AndroidX ComponentActivity provides essential integration points for modern Jetpack components including ViewModel lifecycle scoping, Compose setContent, and ActivityResultContracts that are required across all detected entry points +- Hilt dependency injection framework requires @AndroidEntryPoint annotation on Activity classes to generate proper injection code, as evidenced by consistent annotation usage across CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, and MainActivity +- Separation of specialized Activity implementations (credential provider, auth callback, autofill callback, main UI) enables clear Intent routing and system integration boundaries while maintaining consistent lifecycle and dependency injection patterns + +## Consequences + +Positive: +- Standardized Activity base classes ensure consistent lifecycle management, state preservation through Bundle, and ViewModel integration across all application entry points +- AndroidX ComponentActivity compatibility enables seamless integration with Jetpack Compose UI toolkit and modern activity result contracts +- Hilt @AndroidEntryPoint annotation provides compile-time verified dependency injection reducing runtime errors and boilerplate code +- Specialized Activity implementations create clear architectural boundaries for different system integration flows improving maintainability and testability + +Negative: +- Dependency on AndroidX libraries creates framework coupling and requires ongoing migration as AndroidX evolves +- Hilt code generation increases build time and adds annotation processing complexity to the build pipeline +- Multiple Activity entry points increase application component count and manifest complexity +- Activity lifecycle complexity requires careful state management and Intent handling to avoid memory leaks and configuration change issues + +## Alternatives + +- Use single Activity architecture with Navigation component and Fragment-based flows (rejected) + Rejected because: System integration points (credential provider, autofill service, OAuth callbacks) require distinct Activity entry points declared in AndroidManifest with specific intent filters that cannot be consolidated into single Activity + When valid: Valid for internal application navigation flows that do not require system-level Intent routing +- Use plain android.app.Activity without AndroidX dependencies (rejected) + Rejected because: Would lose ViewModel lifecycle integration, Compose compatibility, and modern activity result contracts, requiring significant custom implementation of lifecycle management and state preservation + When valid: Valid only for minimal applications without ViewModel, Compose, or complex lifecycle requirements +- Use manual dependency injection without Hilt framework (rejected) + Rejected because: Would require custom dependency graph management, manual lifecycle-aware injection, and increased boilerplate across 8+ Activity and ViewModel implementations + When valid: Valid for small applications with minimal dependency graphs or when avoiding annotation processing overhead is critical + +## Risks + +- AndroidX library version conflicts or breaking changes during upgrades may require significant refactoring across all Activity implementations + Mitigation: Pin AndroidX versions in dependency management, test upgrades in isolated branch, maintain comprehensive integration tests covering Activity lifecycle and Intent handling + Owner: Engineering team +- Hilt code generation failures or annotation processing errors may block builds with unclear error messages + Mitigation: Enable Hilt verbose logging, maintain Hilt version compatibility matrix, document common annotation processing issues and resolutions + Owner: Engineering team +- Activity lifecycle complexity and Intent routing logic may introduce memory leaks or state inconsistencies across configuration changes + Mitigation: Implement LeakCanary for memory leak detection, use ViewModel for configuration-change-surviving state, add lifecycle logging for debugging, enforce code review for Intent handling + Owner: Engineering team + +## Implementation Notes + +- Extend androidx.activity.ComponentActivity for Compose-based Activities or androidx.appcompat.app.AppCompatActivity for View-based Activities with AppCompat theme support +- Annotate Activity classes with @AndroidEntryPoint and ViewModel classes with @HiltViewModel to enable Hilt dependency injection +- Use androidx.activity.viewModels() delegation in Activity onCreate to obtain ViewModel instances with proper lifecycle scoping +- Implement Intent handling in onCreate and onNewIntent methods, routing Intent data to ViewModel through sealed action classes (e.g., IntentReceive, ReceiveFirstIntent) +- Declare Activity entry points in AndroidManifest.xml with appropriate intent filters for system integration (credential provider, autofill, OAuth callback schemes) +- Use BaseViewModel as common parent class for ViewModels to standardize state management patterns and lifecycle handling + +## Continuation Context + + +Verify commands: +- grep -r "extends ComponentActivity\|extends AppCompatActivity" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "androidx.activity.viewModels" app/src/main/kotlin --include="*Activity.kt" | wc -l + +Accept when: +- All Activity classes extend either androidx.activity.ComponentActivity or androidx.appcompat.app.AppCompatActivity +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes are annotated with @HiltViewModel and obtained through androidx.activity.viewModels delegation +- Specialized Activity implementations exist for distinct system integration points (credential provider, auth callback, autofill callback, main UI) + +## Enforcement + +- Verified by: Static analysis scanning for Activity base class inheritance patterns +- Verified by: Lint rules checking @AndroidEntryPoint annotation presence on Activity classes with @Inject dependencies +- Verified by: Code review verification of ViewModel instantiation using viewModels delegation +- Verified by: CI pipeline checks for AndroidManifest Activity declarations matching implementation files +- Violation handling: CI build fails if Activity classes do not extend approved AndroidX base classes +- Violation handling: Lint warnings escalated to errors for missing @AndroidEntryPoint on Activities with injected dependencies +- Violation handling: Code review blocks merge if ViewModel instantiation bypasses viewModels delegation without documented justification +- Violation handling: Architecture review required for new Activity entry points to ensure proper system integration boundaries +- Exception process: Document exception rationale in ADR amendment or inline code comments with EXCEPTION: prefix +- Exception process: Obtain architecture team approval for Activity implementations using non-standard base classes +- Exception process: Create tracking issue for temporary exceptions with migration plan and target completion date +- Exception process: Review exceptions quarterly to assess migration progress and update enforcement rules \ No newline at end of file diff --git a/docs/adr/de0b6d27-1fae-4b8c-9a96-2aa4ce519252-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-files.md b/docs/adr/de0b6d27-1fae-4b8c-9a96-2aa4ce519252-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-files.md new file mode 100644 index 00000000000..f2b6416eb90 --- /dev/null +++ b/docs/adr/de0b6d27-1fae-4b8c-9a96-2aa4ce519252-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-python-test-files.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Python Test Files + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. MUST: Python test files MUST use unittest as the test framework with unittest.TestCase as the base class for test suites + +## Policy Block + +- MUST Python test files MUST use unittest as the test framework with unittest.TestCase as the base class for test suites + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/deada6b8-5256-42f2-9304-3c6fcf5b13a9-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md b/docs/adr/deada6b8-5256-42f2-9304-3c6fcf5b13a9-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md new file mode 100644 index 00000000000..6282ee9db02 --- /dev/null +++ b/docs/adr/deada6b8-5256-42f2-9304-3c6fcf5b13a9-standardize-unittest-based-test-contracts-with-setup-teardown-lifecycle-test-classes-implement.md @@ -0,0 +1,116 @@ +# Standardize unittest-based Test Contracts with setUp/tearDown Lifecycle: Test Classes Implement + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test validation scripts in .github/scripts/ use unittest.TestCase with explicit setUp and tearDown methods to manage test fixtures and resource lifecycle +- The codebase demonstrates a pattern of defining public test contracts through named test methods (test_validate_json_valid, test_validate_json_invalid, test_find_duplicates) that serve as executable specifications +- Test fixtures are managed through file-based resources (sample-valid1.json, sample-valid2.json, sample-invalid.json) initialized in setUp and cleaned up in tearDown +- The pattern appears in CI/CD validation scripts that verify JSON structure and detect duplicates, requiring consistent test isolation and repeatable execution +- Public contracts are exposed through utility functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that are tested through integration-style tests + +## Problem Statement + +Testing scripts lack a consistent approach to test lifecycle management, fixture initialization, and contract definition, leading to potential test pollution, unclear test boundaries, and difficulty in maintaining repeatable test execution across CI/CD pipelines. + +## Decision + +1. MUST: Test classes MUST implement tearDown method to clean up resources, restore state, and prevent test pollution + +## Policy Block + +- MUST Test classes MUST implement tearDown method to clean up resources, restore state, and prevent test pollution + +In scope: +- Python test files in .github/scripts/ directory +- Validation scripts that verify JSON structure, configuration, or CI/CD artifacts +- Integration tests that validate public API contracts of utility functions +- Test classes that require fixture initialization or resource cleanup + +Out of scope: +- End-to-end tests that span multiple services or repositories +- Performance or load tests that require different lifecycle management +- Mock-heavy unit tests where fixtures are constructed inline +- Tests in application code outside of CI/CD scripts + +## Rationale + +- The unittest framework provides standardized test discovery, execution, and reporting that integrates with CI/CD pipelines without additional tooling +- setUp and tearDown methods enforce test isolation by ensuring each test starts with clean state and cleans up after itself, preventing cascading failures +- Named test methods with descriptive names serve as living documentation of the public contracts and expected behaviors of utility functions +- File-based fixtures enable realistic integration testing of JSON validation and file processing logic without requiring complex mocking + +## Consequences + +Positive: +- Consistent test lifecycle management prevents test pollution and ensures repeatable execution across local and CI environments +- Clear test method naming creates self-documenting contracts that communicate expected behavior to maintainers +- Standardized unittest.TestCase inheritance enables test discovery and execution through standard Python tooling +- Explicit setUp/tearDown methods make resource management visible and auditable + +Negative: +- setUp/tearDown runs before/after every test method, which may introduce overhead for expensive fixture initialization +- unittest framework is more verbose than modern alternatives like pytest, requiring more boilerplate code +- File-based fixtures require careful path management and may be fragile across different execution environments +- Test isolation through setUp/tearDown may hide integration issues that would surface with shared state + +## Alternatives + +- Use pytest with fixtures and dependency injection instead of unittest.TestCase (rejected) + Rejected because: Evidence shows existing codebase uses unittest.TestCase consistently; migration would require rewriting existing tests without clear benefit for CI/CD validation scripts + When valid: For new projects or when advanced fixture scoping (function, module, session) is required +- Inline fixture construction within each test method without setUp/tearDown (rejected) + Rejected because: Would duplicate fixture initialization code across test methods and eliminate guaranteed cleanup, increasing risk of test pollution + When valid: For simple tests with trivial fixtures that require no cleanup +- Use setUpClass/tearDownClass for shared fixtures across all test methods (deferred) + When valid: When fixture initialization is expensive and tests can safely share state without pollution risk + +## Risks + +- File-based fixtures may fail if executed from unexpected working directories or in containerized CI environments + Mitigation: Use os.path.join with __file__ and os.path.dirname to construct relative paths that work regardless of execution context + Owner: CI/CD engineering team +- setUp/tearDown overhead may slow test execution if fixtures are expensive to initialize + Mitigation: Profile test execution time and consider setUpClass/tearDownClass for expensive fixtures that can be safely shared + Owner: Test infrastructure team +- Incomplete tearDown implementation may leave resources open or state modified, causing cascading test failures + Mitigation: Use try/finally blocks or context managers in tearDown to ensure cleanup runs even if tests fail + Owner: Engineering team + +## Implementation Notes + +- Store test fixtures in a fixtures/ subdirectory adjacent to test files, using descriptive names like sample-valid1.json, sample-invalid.json +- Construct fixture paths using os.path.join(os.path.dirname(__file__), 'fixtures/filename') to ensure portability across execution environments +- Use patch('sys.stdout', new=io.StringIO()) in setUp and stop in tearDown to suppress output from CLI utilities during testing +- Name test methods with test_ prefix followed by descriptive names that communicate the contract being validated (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) +- Include docstrings in test methods that explain what contract or behavior is being validated + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest\.TestCase' .github/scripts/ +- grep -r 'def setUp\(self\):' .github/scripts/ +- grep -r 'def tearDown\(self\):' .github/scripts/ +- python -m unittest discover -s .github/scripts/ -p 'test_*.py' + +Accept when: +- All test classes in .github/scripts/ inherit from unittest.TestCase +- Test classes that use fixtures implement both setUp and tearDown methods +- Test methods follow test_* naming convention and include docstrings +- All tests pass when executed via unittest discovery + +## Enforcement + +- Verified by: CI pipeline runs unittest discovery on all test_*.py files in .github/scripts/ +- Verified by: Code review checklist verifies setUp/tearDown implementation for new test classes +- Verified by: Static analysis checks for unittest.TestCase inheritance in test files +- Violation handling: CI build fails if tests do not follow unittest.TestCase pattern +- Violation handling: Code review blocks merge if setUp/tearDown are missing from test classes that use fixtures +- Violation handling: Linting warnings for test files that do not follow naming conventions +- Exception process: Document rationale in test file comments if alternative pattern is required +- Exception process: Obtain approval from CI/CD engineering team for deviations +- Exception process: Create tracking issue for technical debt if temporary exception is granted \ No newline at end of file diff --git a/docs/adr/deff453e-857e-46da-8a48-4d36fe3dbbd7-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-tool-handlers.md b/docs/adr/deff453e-857e-46da-8a48-4d36fe3dbbd7-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-tool-handlers.md new file mode 100644 index 00000000000..bb164d44eb9 --- /dev/null +++ b/docs/adr/deff453e-857e-46da-8a48-4d36fe3dbbd7-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-public-tool-handlers.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Public Tool Handlers + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. MUST: All public API tool handlers MUST use Zod schemas to validate input parameters before execution + +## Policy Block + +- MUST All public API tool handlers MUST use Zod schemas to validate input parameters before execution + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/e0d37356-1631-46f3-97d8-1f8d05fd6507-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-nested-field-access.md b/docs/adr/e0d37356-1631-46f3-97d8-1f8d05fd6507-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-nested-field-access.md new file mode 100644 index 00000000000..4ef72de5080 --- /dev/null +++ b/docs/adr/e0d37356-1631-46f3-97d8-1f8d05fd6507-standardize-dictionary-get-method-for-safe-field-access-in-integration-testing-nested-field-access.md @@ -0,0 +1,114 @@ +# Standardize Dictionary .get() Method for Safe Field Access in Integration Testing: Nested Field Access + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration scripts in .github/scripts/ interact with external APIs (JIRA, GitHub) where response structures may vary or contain optional fields +- Python's dictionary .get() method provides safe access to potentially missing keys without raising KeyError exceptions +- Two automation scripts (jira_release_notes.py, label-pr.py) demonstrate consistent use of .get() for accessing nested JSON response fields +- The pattern appears in CI/CD automation context where script failures would block workflows and require defensive programming + +## Problem Statement + +Integration scripts that parse external API responses need a consistent approach to handle optional or missing fields without causing runtime exceptions that would fail CI/CD workflows. Direct dictionary key access raises KeyError for missing keys, requiring explicit exception handling or key existence checks throughout the codebase. + +## Decision + +1. SHOULD: Nested field access SHOULD chain .get() calls (e.g., response.get('fields', {}).get('field_name')) to handle missing intermediate keys + +## Policy Block + +- SHOULD Nested field access SHOULD chain .get() calls (e.g., response.get('fields', {}).get('field_name')) to handle missing intermediate keys + +In scope: +- Python scripts in .github/scripts/ that parse JSON responses from external APIs +- Integration test utilities that process configuration files with optional fields +- Automation scripts that interact with GitHub API, JIRA API, or similar external services + +Out of scope: +- Internal data structures where key presence is guaranteed by construction +- Type-checked code using TypedDict or dataclasses where missing keys indicate programming errors +- Performance-critical paths where exception handling overhead is measured and acceptable + +Exceptions: +- EXC-001: API contract explicitly guarantees field presence and KeyError is preferred for contract violations + +## Rationale + +- The evidence shows consistent use of .get() across two independent scripts (jira_release_notes.py, label-pr.py) when accessing fields from external API responses, indicating an established pattern +- Using .get() prevents KeyError exceptions in CI/CD automation where script failures would block workflows and require manual intervention +- The pattern appears specifically in integration contexts (testing.integration facet) where external system responses are unpredictable +- Python's .get() method provides a concise, readable alternative to try-except blocks or explicit key existence checks + +## Consequences + +Positive: +- Reduced runtime exceptions in CI/CD workflows from missing or optional API response fields +- More resilient integration scripts that gracefully handle API schema variations +- Cleaner code without verbose try-except blocks or 'key in dict' checks +- Easier debugging with explicit default values visible at access points + +Negative: +- Silent failures possible if default values mask actual API errors or schema changes +- Potential confusion between missing keys (None) and explicit null values without additional checks +- May hide API contract violations that should be caught and reported +- Slightly less explicit than try-except blocks for documenting expected vs. exceptional cases + +## Alternatives + +- Use try-except blocks with KeyError handling for all dictionary access (rejected) + Rejected because: More verbose and reduces code readability; evidence shows .get() is preferred pattern in existing scripts + When valid: When explicit exception handling logic is needed or when distinguishing KeyError from other exceptions is important +- Use 'key in dict' checks before accessing each field (rejected) + Rejected because: Requires two dictionary lookups and increases code verbosity; .get() is more idiomatic Python + When valid: When the presence check itself needs to trigger different logic paths beyond default values +- Parse responses into typed dataclasses with validation (deferred) + Rejected because: Would require additional dependencies (pydantic, attrs) and refactoring; may be considered for future enhancement + When valid: For complex response schemas where full validation and type safety are required + +## Risks + +- API schema changes may go undetected if missing fields are silently handled with defaults + Mitigation: Log warnings when expected fields are missing; implement schema validation tests for critical API endpoints + Owner: Engineering team +- Inconsistent default value choices across scripts may lead to unexpected behavior + Mitigation: Document standard default values for common field types; review default choices in code review + Owner: Engineering team +- Overuse of .get() may mask programming errors in internal data structures + Mitigation: Limit .get() usage to external API boundaries as defined in policy scope; use direct access for internal structures + Owner: Engineering team + +## Implementation Notes + +- When accessing nested fields, use .get() with empty dict default for intermediate keys: response.get('fields', {}).get('field_name') +- Choose default values that make sense for the business logic: empty string for text, empty list for collections, None when absence needs explicit handling +- Add comments documenting why a field might be missing when using .get() for non-obvious cases +- Consider logging at debug level when .get() returns a default value to aid troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r '\.get(' .github/scripts/*.py | wc -l +- grep -r '\["' .github/scripts/*.py | grep -v '.get' | wc -l +- python -m py_compile .github/scripts/*.py + +Accept when: +- Integration scripts in .github/scripts/ use .get() for all external API response field access +- Direct bracket notation is used only for guaranteed fields with documented justification +- Scripts execute without KeyError exceptions when processing API responses with optional fields + +## Enforcement + +- Verified by: Code review for new integration scripts +- Verified by: Grep-based verification in CI to detect bracket notation in API response handling +- Verified by: Runtime monitoring of CI/CD workflow failures +- Violation handling: Code review feedback requesting .get() usage for external API access +- Violation handling: CI workflow failures due to KeyError trigger review of dictionary access patterns +- Violation handling: Documentation updates if legitimate exceptions are identified +- Exception process: Document API contract guarantee in code comments +- Exception process: Obtain code review approval with explicit justification +- Exception process: Add to exception registry with EXC-001 reference \ No newline at end of file diff --git a/docs/adr/e293d8ea-c655-4557-92c6-da3bd24018b1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-implemented.md b/docs/adr/e293d8ea-c655-4557-92c6-da3bd24018b1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-implemented.md new file mode 100644 index 00000000000..25824b61f10 --- /dev/null +++ b/docs/adr/e293d8ea-c655-4557-92c6-da3bd24018b1-adopt-async-handler-pattern-with-zod-validation-for-public-api-tools-tool-handlers-implemented.md @@ -0,0 +1,112 @@ +# Adopt Async Handler Pattern with Zod Validation for Public API Tools: Tool Handlers Implemented + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-server MCP implements public API tools (capture, tapAt, findElementWithObstruction) that require consistent input validation and asynchronous execution patterns +- Each tool handler coordinates with external ADB processes and filesystem operations, necessitating async/await concurrency control +- Zod schema validation is used uniformly across tool entry points to enforce type safety and provide default values before handler execution +- The pattern separates validation concerns (Zod schemas) from execution logic (async handler functions), enabling reusable validation utilities imported from '../utils/validation.js' + +## Problem Statement + +Public API tools in the android-device-server require a consistent approach to input validation, error handling, and asynchronous coordination with external processes (ADB) and I/O operations (filesystem, path resolution). Without standardized validation schemas and handler patterns, each tool would implement validation inconsistently, leading to runtime errors, poor developer experience, and difficulty maintaining contract stability across the API surface. + +## Decision + +1. MUST: Tool handlers MUST be implemented as async functions to coordinate with ADB operations and filesystem I/O + +## Policy Block + +- MUST Tool handlers MUST be implemented as async functions to coordinate with ADB operations and filesystem I/O + +In scope: +- All tool handlers in src/tools/ directory that expose public API contracts +- Input validation for parameters passed to capture, tapAt, and findElementWithObstruction functions +- Async coordination with ADB shell commands and filesystem operations + +Out of scope: +- Internal utility functions that do not expose public API contracts +- Synchronous helper functions that do not coordinate with external processes +- Test fixtures and mock implementations + +## Rationale + +- Zod provides runtime type safety and schema validation that complements TypeScript's compile-time checks, preventing invalid inputs from reaching handler logic +- The async handler pattern enables non-blocking coordination with ADB processes and filesystem operations, which are inherently asynchronous and I/O-bound +- Centralizing validation utilities in '../utils/validation.js' reduces duplication and ensures consistent error messages across the API surface +- Named exports for contracts (capture, tapAt, FindElementResult, findElementWithObstruction) establish clear API boundaries and facilitate tree-shaking in consuming code + +## Consequences + +Positive: +- Input validation errors are caught early with descriptive Zod error messages before handler execution +- Async handlers enable efficient coordination with external ADB processes without blocking the event loop +- Consistent validation patterns across tools reduce cognitive load for developers adding new API endpoints +- Type-safe schemas with defaults reduce boilerplate in handler implementations and improve API ergonomics + +Negative: +- Zod adds runtime overhead for schema validation on every API call, though this is typically negligible compared to ADB operation latency +- Async/await patterns require careful error handling to prevent unhandled promise rejections +- Developers must learn Zod schema syntax in addition to TypeScript type annotations +- Validation schemas must be kept in sync with TypeScript types, creating potential for drift + +## Alternatives + +- Use plain TypeScript types without runtime validation (rejected) + Rejected because: TypeScript types are erased at runtime and provide no protection against invalid inputs from external callers or dynamic data sources + When valid: Only valid for internal functions with guaranteed compile-time type safety +- Implement custom validation functions for each tool handler (rejected) + Rejected because: Custom validation leads to inconsistent error handling, duplicated logic, and higher maintenance burden across the API surface + When valid: Valid for highly specialized validation logic that cannot be expressed in Zod schemas +- Use synchronous handlers with callback-based ADB operations (rejected) + Rejected because: Callback-based patterns are harder to reason about, compose, and error-handle compared to async/await, and do not align with modern Node.js idioms + When valid: Valid only for legacy codebases or environments without async/await support + +## Risks + +- Zod schema validation failures may produce cryptic error messages that are difficult for API consumers to debug + Mitigation: Wrap Zod validation in error handling that transforms validation errors into user-friendly messages with field-level details + Owner: engineering team +- Async handlers may introduce race conditions when multiple tools access shared ADB state concurrently + Mitigation: Implement request queuing or locking mechanisms in the ADB module to serialize operations that cannot safely run in parallel + Owner: engineering team +- Schema drift between Zod validation and TypeScript types may allow type-unsafe code to pass validation + Mitigation: Use Zod's z.infer<> utility to derive TypeScript types from schemas, ensuring single source of truth + Owner: engineering team + +## Implementation Notes + +- Import Zod at the top of each tool module: import { z } from 'zod' +- Define validation schemas as const objects before handler functions, using z.object() with field-level constraints +- Use schema.parse() or schema.safeParse() at the entry point of each handler to validate inputs before proceeding +- Ensure all async handlers properly await ADB operations and filesystem calls, and wrap in try/catch for error handling +- Export both the handler function and any result types (e.g., FindElementResult) as named exports for API consumers + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" src/tools/ | wc -l +- grep -r "async.*handler\|async function" src/tools/*.ts | wc -l +- grep -r "z\.object({" src/tools/*.ts | wc -l + +Accept when: +- All tool files in src/tools/ import Zod and define at least one z.object() schema +- All public API handlers (capture, tapAt, findElementWithObstruction) are declared as async functions +- Verification commands show consistent usage of Zod schemas across at least 3 tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for all new public API tools +- Verified by: Static analysis with ESLint rules enforcing async handler signatures +- Verified by: CI pipeline grep checks verifying presence of Zod imports and z.object() schemas in src/tools/ +- Violation handling: Pull requests adding new tools without Zod validation are blocked until schemas are added +- Violation handling: Existing tools without validation are flagged for refactoring in technical debt backlog +- Violation handling: Runtime errors from unvalidated inputs are escalated as P1 bugs requiring immediate schema addition +- Exception process: Exceptions require written justification documenting why Zod validation is infeasible for the specific tool +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in tool module comments with rationale and expiration date for review \ No newline at end of file diff --git a/docs/adr/e4caeb99-f530-4d0f-baad-a803acfbb9d2-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-modules.md b/docs/adr/e4caeb99-f530-4d0f-baad-a803acfbb9d2-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-modules.md new file mode 100644 index 00000000000..c2f17c8a6eb --- /dev/null +++ b/docs/adr/e4caeb99-f530-4d0f-baad-a803acfbb9d2-adopt-unittest-and-vitest-as-standard-testing-frameworks-python-test-modules.md @@ -0,0 +1,113 @@ +# Adopt unittest and vitest as Standard Testing Frameworks: Python Test Modules + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains Python validation scripts in .github/scripts/validate-json/ that require unit testing for JSON validation and duplicate detection logic +- TypeScript parser modules in .claude/mcp/android-device-server/src/parsers/ require testing for dumpsys output parsing and window overlay detection +- Both Python and TypeScript components use language-native testing frameworks (unittest for Python, vitest for TypeScript) with structured test class organization and describe/it patterns +- Test fixtures are organized in dedicated directories (fixtures/) and tests follow naming conventions (test_* for Python, *.spec.ts for TypeScript) + +## Problem Statement + +The codebase spans multiple languages (Python and TypeScript) with distinct testing requirements for validation scripts and parser modules, requiring a consistent testing strategy that accommodates language-specific testing frameworks while maintaining uniform test organization, fixture management, and verification patterns across the project. + +## Decision + +1. MUST: Python test modules MUST use unittest.TestCase as the base class for test organization + +## Policy Block + +- MUST Python test modules MUST use unittest.TestCase as the base class for test organization + +In scope: +- All Python test modules in .github/scripts/*/test_*.py +- All TypeScript test modules in .claude/mcp/**/src/**/*.spec.ts +- Unit tests for validation logic, parser modules, and utility functions +- Test fixture management and organization + +Out of scope: +- Integration tests requiring external services or databases +- End-to-end tests requiring full system deployment +- Performance or load testing frameworks +- Language-specific testing beyond Python and TypeScript + +## Rationale + +- The evidence shows consistent use of unittest in Python modules (.github/scripts/validate-json/test_validate_json.py) with TestCase classes, setUp/tearDown lifecycle methods, and assertion methods (assertTrue, assertFalse, assertEqual, assertIn) +- The evidence shows vitest adoption in TypeScript modules (.claude/mcp/android-device-server/src/parsers/dumpsys.spec.ts) with describe/it block structure for organizing test suites and individual test cases +- Both frameworks provide language-native testing capabilities with minimal external dependencies, reducing tooling complexity and maintenance overhead +- The pattern demonstrates mature test organization with fixture management, lifecycle hooks, and comprehensive coverage of both valid and invalid input scenarios + +## Consequences + +Positive: +- Language-native frameworks reduce learning curve for developers familiar with Python or TypeScript ecosystems +- unittest and vitest provide comprehensive assertion libraries and test organization patterns without additional dependencies +- Consistent test structure across modules improves code readability and maintainability +- Fixture-based testing enables reliable test isolation and repeatable test execution + +Negative: +- Multi-language testing strategy requires maintaining knowledge of two distinct testing frameworks and their conventions +- Test execution requires separate commands and tooling for Python (unittest) and TypeScript (vitest) test suites +- Cross-language test reporting and aggregation requires additional tooling or manual consolidation +- Framework-specific features may not be portable between Python and TypeScript test suites + +## Alternatives + +- Adopt pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows existing unittest implementation with TestCase classes, setUp/tearDown methods, and assertion patterns already established in the codebase; migration would require rewriting existing tests without clear benefit + When valid: For new Python projects without existing unittest investment, or when advanced pytest features (fixtures, parametrization, plugins) are required +- Use Jest instead of vitest for TypeScript testing (rejected) + Rejected because: Evidence shows vitest already adopted in TypeScript modules; Jest would provide similar capabilities but require migration of existing test suites and configuration + When valid: For projects requiring Jest-specific ecosystem integrations or when team expertise is concentrated in Jest +- Consolidate to a single cross-language testing framework (rejected) + Rejected because: No evidence of cross-language testing framework usage; language-native frameworks provide better integration with respective ecosystems and tooling + When valid: For projects with extensive cross-language integration testing requirements or unified test reporting needs + +## Risks + +- Developers may introduce inconsistent testing patterns when working across Python and TypeScript modules + Mitigation: Document testing conventions in project README or CONTRIBUTING.md; provide example test templates for each language; enforce conventions through code review + Owner: engineering team +- Test coverage may diverge between Python and TypeScript modules due to framework capability differences + Mitigation: Establish minimum coverage requirements applicable to both languages; use language-specific coverage tools (coverage.py, vitest coverage) with unified reporting thresholds + Owner: engineering team +- CI/CD pipeline complexity increases with multiple test framework execution and reporting requirements + Mitigation: Implement parallel test execution for Python and TypeScript suites; use unified CI reporting format (JUnit XML) for aggregated test results + Owner: engineering team + +## Implementation Notes + +- Python tests should import unittest and create test classes inheriting from unittest.TestCase with test methods prefixed by test_ +- TypeScript tests should import describe, it, and expect from vitest and organize tests in describe blocks with individual test cases in it blocks +- Test fixtures should be placed in fixtures/ subdirectories relative to test files and loaded using os.path.join (Python) or node:path (TypeScript) +- Use setUp/tearDown (Python) or beforeEach/afterEach (TypeScript) for test lifecycle management including resource initialization and cleanup + +## Continuation Context + + +Verify commands: +- grep -r 'class.*unittest.TestCase' .github/scripts/*/test_*.py +- grep -r "from 'vitest'" .claude/mcp/**/src/**/*.spec.ts +- find . -name 'test_*.py' -o -name '*.spec.ts' | wc -l + +Accept when: +- All Python test files use unittest.TestCase base class and test_* method naming convention +- All TypeScript test files use vitest with describe/it structure and *.spec.ts naming convention +- Test fixtures are organized in dedicated fixtures/ directories with proper path resolution + +## Enforcement + +- Verified by: Code review verification of test file structure and framework usage +- Verified by: CI pipeline execution of unittest (Python) and vitest (TypeScript) test suites +- Verified by: Automated linting rules checking test file naming conventions +- Violation handling: Pull requests introducing tests with non-standard frameworks or conventions are rejected during code review +- Violation handling: CI pipeline fails if test files do not follow naming conventions or framework patterns +- Violation handling: Documentation and examples are updated to reflect correct testing patterns +- Exception process: Exceptions require architectural review and documentation of rationale in ADR or technical design document +- Exception process: Exception approval requires demonstration that standard frameworks cannot meet specific testing requirements +- Exception process: Approved exceptions are documented in project testing guidelines with scope and justification \ No newline at end of file diff --git a/docs/adr/e555e1eb-f5f2-4d66-ae3c-34b596cf39dc-adopt-model-context-protocol-sdk-for-android-device-integration-type-definitions-imported.md b/docs/adr/e555e1eb-f5f2-4d66-ae3c-34b596cf39dc-adopt-model-context-protocol-sdk-for-android-device-integration-type-definitions-imported.md new file mode 100644 index 00000000000..1f1736ba947 --- /dev/null +++ b/docs/adr/e555e1eb-f5f2-4d66-ae3c-34b596cf39dc-adopt-model-context-protocol-sdk-for-android-device-integration-type-definitions-imported.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Type Definitions Imported + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. MUST: Type definitions MUST be imported from @modelcontextprotocol/sdk/types.js to ensure protocol compliance + +## Policy Block + +- MUST Type definitions MUST be imported from @modelcontextprotocol/sdk/types.js to ensure protocol compliance + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/e58a0565-70ba-4773-89f2-1b12438a06f6-adopt-model-context-protocol-sdk-for-android-device-integration-tool-lookup-use.md b/docs/adr/e58a0565-70ba-4773-89f2-1b12438a06f6-adopt-model-context-protocol-sdk-for-android-device-integration-tool-lookup-use.md new file mode 100644 index 00000000000..b5df3f5f80b --- /dev/null +++ b/docs/adr/e58a0565-70ba-4773-89f2-1b12438a06f6-adopt-model-context-protocol-sdk-for-android-device-integration-tool-lookup-use.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Tool Lookup Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. SHOULD: Tool lookup SHOULD use array find operations on registered tool collections by name + +## Policy Block + +- SHOULD Tool lookup SHOULD use array find operations on registered tool collections by name + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/e61011fa-9c21-47e2-bfeb-aa5f1be29b09-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-assignment-logic.md b/docs/adr/e61011fa-9c21-47e2-bfeb-aa5f1be29b09-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-assignment-logic.md new file mode 100644 index 00000000000..cd158b56216 --- /dev/null +++ b/docs/adr/e61011fa-9c21-47e2-bfeb-aa5f1be29b09-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-label-assignment-logic.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Label Assignment Logic + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. MUST: Label assignment logic MUST evaluate both title_patterns and path_patterns from configuration to determine applicable labels + +## Policy Block + +- MUST Label assignment logic MUST evaluate both title_patterns and path_patterns from configuration to determine applicable labels + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/ea4b543d-d0be-4462-9fa3-fa0b2f2fe57d-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-android-activities-requiring.md b/docs/adr/ea4b543d-d0be-4462-9fa3-fa0b2f2fe57d-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-android-activities-requiring.md new file mode 100644 index 00000000000..8cd4b7c94ce --- /dev/null +++ b/docs/adr/ea4b543d-d0be-4462-9fa3-fa0b2f2fe57d-adopt-hilt-dependency-injection-for-android-component-lifecycle-management-android-activities-requiring.md @@ -0,0 +1,126 @@ +# Adopt Hilt Dependency Injection for Android Component Lifecycle Management: Android Activities Requiring + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Android application requires dependency injection to manage component lifecycles across Activities, ViewModels, and Application classes +- Hilt provides Android-specific annotations (@AndroidEntryPoint, @HiltViewModel, @Inject) that integrate with the Android component lifecycle +- Eight files across the codebase demonstrate consistent usage of Hilt annotations for Activities (CredentialProviderActivity, AuthCallbackActivity, AutofillCallbackActivity, MainActivity), ViewModels (CredentialProviderViewModel, AuthCallbackViewModel, AutofillCallbackViewModel), and Application (BitwardenApplication) +- The pattern spans critical authentication, autofill, and credential provider flows requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's compile-time code generation ensures type-safe dependency graphs without runtime reflection overhead + +## Problem Statement + +Android applications require a dependency injection framework that understands Android component lifecycles, provides compile-time safety, and integrates seamlessly with Activities, ViewModels, and Application classes without manual factory creation or runtime reflection penalties. + +## Decision + +1. MUST: All Android Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint + +## Policy Block + +- MUST All Android Activities requiring dependency injection MUST be annotated with @AndroidEntryPoint + +In scope: +- Android Activities (ComponentActivity, AppCompatActivity subclasses) +- Android ViewModels (BaseViewModel subclasses) +- Android Application class +- Authentication flows (AuthCallbackActivity, AuthCallbackViewModel) +- Autofill flows (AutofillCallbackActivity, AutofillCallbackViewModel) +- Credential provider flows (CredentialProviderActivity, CredentialProviderViewModel) +- Main application entry point (MainActivity, BitwardenApplication) + +Out of scope: +- Non-Android Kotlin classes without lifecycle dependencies +- Pure domain logic classes that can use constructor injection without annotations +- Test fixtures and test doubles +- Third-party library integrations that provide their own DI mechanisms + +Exceptions: +- EXC-001: Legacy Activities not yet migrated to Hilt may temporarily use manual dependency construction + +## Rationale + +- The evidence shows consistent Hilt annotation usage across 8 files spanning Activities, ViewModels, and Application classes, demonstrating an established architectural pattern +- Hilt's Android-specific annotations (@AndroidEntryPoint, @HiltViewModel) provide compile-time code generation that eliminates boilerplate factory code while maintaining type safety +- The pattern appears in critical flows (authentication, autofill, credential provider) requiring managed dependencies like AuthRepository, CredentialProviderRequestManager, and BitwardenCredentialManager +- Hilt's integration with androidx.activity.viewModels and androidx.lifecycle components ensures proper scoping and lifecycle management without manual cleanup + +## Consequences + +Positive: +- Compile-time dependency graph validation prevents runtime injection failures +- Automatic lifecycle management reduces memory leaks from improper component cleanup +- Reduced boilerplate code through annotation-driven code generation +- Type-safe dependency injection without reflection overhead +- Seamless integration with Android Jetpack components (ViewModels, Activities, Compose) + +Negative: +- Increased build time due to annotation processing and code generation +- Additional complexity in build configuration requiring Hilt Gradle plugin and kapt +- Learning curve for developers unfamiliar with Hilt-specific annotations and scoping rules +- Tight coupling to Hilt framework makes migration to alternative DI solutions costly + +## Alternatives + +- Manual dependency injection through constructor parameters and factory patterns (rejected) + Rejected because: Requires extensive boilerplate factory code for ViewModels and Activities, lacks compile-time validation, and increases maintenance burden across 8+ component files + When valid: Valid for small applications with fewer than 5 components requiring injection +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, lacks lifecycle-aware scoping, and demands significantly more boilerplate than Hilt + When valid: Valid for non-Android Kotlin projects or when maximum control over component graphs is required +- Koin runtime dependency injection framework (rejected) + Rejected because: Uses runtime reflection instead of compile-time code generation, lacks type-safe dependency resolution, and provides no compile-time validation of dependency graphs + When valid: Valid for prototypes or applications prioritizing fast build times over runtime safety + +## Risks + +- Annotation processing failures during build may cause cryptic compilation errors without clear resolution paths + Mitigation: Establish clear build troubleshooting documentation, enable verbose kapt logging, and maintain Hilt version compatibility with Kotlin compiler + Owner: Engineering team +- Improper scope usage (e.g., ActivityScoped dependencies in ViewModels) may cause memory leaks or unexpected lifecycle behavior + Mitigation: Implement code review checklist for Hilt scope annotations, add lint rules to detect scope mismatches, and provide team training on Hilt scoping rules + Owner: Architecture team +- Increased build times from annotation processing may slow development iteration cycles + Mitigation: Enable Gradle build caching, use incremental annotation processing, and monitor build performance metrics to identify optimization opportunities + Owner: DevOps team + +## Implementation Notes + +- Ensure all Activities requiring injection extend ComponentActivity or AppCompatActivity before applying @AndroidEntryPoint +- Use androidx.activity.viewModels() delegate for ViewModel injection in Activities annotated with @AndroidEntryPoint +- Configure Hilt Gradle plugin in app/build.gradle.kts and apply kapt for annotation processing +- Create Hilt modules for dependencies that cannot use constructor injection (interfaces, third-party classes, Android framework types) +- Follow Hilt scoping guidelines: @Singleton for application-wide, @ActivityScoped for Activity lifecycle, @ViewModelScoped for ViewModel lifecycle + +## Continuation Context + + +Verify commands: +- grep -r "@AndroidEntryPoint" app/src/main/kotlin --include="*Activity.kt" | wc -l +- grep -r "@HiltViewModel" app/src/main/kotlin --include="*ViewModel.kt" | wc -l +- grep -r "@Inject" app/src/main/kotlin/com/x8bit/bitwarden/BitwardenApplication.kt + +Accept when: +- All Activity classes requiring dependency injection are annotated with @AndroidEntryPoint +- All ViewModel classes requiring dependency injection are annotated with @HiltViewModel +- The Application class uses @Inject for application-scoped dependencies +- Verification commands return non-zero counts indicating Hilt annotation presence + +## Enforcement + +- Verified by: Code review checklist requiring Hilt annotations on new Activities and ViewModels +- Verified by: Automated lint rules detecting Activities/ViewModels with constructor parameters but missing Hilt annotations +- Verified by: CI build pipeline validation ensuring annotation processing completes successfully +- Verified by: Static analysis tools scanning for improper scope usage or missing @AndroidEntryPoint annotations +- Violation handling: Pull requests missing required Hilt annotations on Activities or ViewModels are blocked until corrected +- Violation handling: Build failures from annotation processing errors must be resolved before merge +- Violation handling: Code review identifies manual dependency construction in Android components and requests Hilt migration +- Violation handling: Quarterly architecture reviews audit Hilt usage patterns and identify non-compliant components +- Exception process: Submit exception request to architecture team with justification for manual dependency injection +- Exception process: Document exception rationale in code comments with @SuppressLint("HiltMigration") annotation +- Exception process: Exceptions require approval from two architecture team members +- Exception process: All exceptions must include migration plan with target completion date \ No newline at end of file diff --git a/docs/adr/ebc960ca-53bf-4ba9-9e24-ba3551bc90e3-adopt-model-context-protocol-sdk-for-android-device-integration-server-initialization-declare.md b/docs/adr/ebc960ca-53bf-4ba9-9e24-ba3551bc90e3-adopt-model-context-protocol-sdk-for-android-device-integration-server-initialization-declare.md new file mode 100644 index 00000000000..e3e4839e7d1 --- /dev/null +++ b/docs/adr/ebc960ca-53bf-4ba9-9e24-ba3551bc90e3-adopt-model-context-protocol-sdk-for-android-device-integration-server-initialization-declare.md @@ -0,0 +1,123 @@ +# Adopt Model Context Protocol SDK for Android Device Integration: Server Initialization Declare + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all Android device integration implementations using the Model Context Protocol. + +## Context + +- The android-device-mcp server requires standardized protocol communication between AI models and Android device tooling +- The @modelcontextprotocol/sdk library provides server capabilities, stdio transport, and type definitions for MCP-compliant integrations +- Tool registration and execution patterns require structured error handling with console.error logging for tool errors and fatal errors +- The server initialization pattern uses capability declarations with tools support and version metadata +- Real-time boundary coordination requires tool lookup patterns using array find operations on registered tool collections + +## Problem Statement + +Android device automation and control requires a standardized integration protocol that enables AI models to discover, invoke, and receive results from device-specific tools while maintaining type safety, error visibility, and transport abstraction across stdio-based communication channels. + +## Decision + +1. MUST: Server initialization MUST declare capabilities with tools support and include name and version metadata + +## Policy Block + +- MUST Server initialization MUST declare capabilities with tools support and include name and version metadata + +In scope: +- Android device MCP server implementations +- Tool registration and capability declaration +- Stdio-based transport communication +- Error handling and logging for tool execution +- Type-safe protocol message handling + +Out of scope: +- Non-MCP integration protocols +- HTTP or WebSocket-based transports +- Client-side MCP implementations +- Non-Android device integrations +- Alternative logging frameworks beyond console.error + +## Rationale + +- The @modelcontextprotocol/sdk provides standardized server construction, stdio transport, and type definitions that ensure protocol compliance across AI model integrations +- Structured error logging with console.error for both tool-level and fatal errors enables debugging and monitoring in stdio-based communication environments +- Capability-based server initialization with tools support allows AI models to discover available device operations through protocol-defined mechanisms +- Modular separation of validation utilities and tool implementations supports maintainability and testing isolation for device-specific operations + +## Consequences + +Positive: +- Standardized protocol integration enables interoperability with any MCP-compliant AI model or client +- Type safety from SDK type definitions reduces runtime protocol errors and improves development experience +- Stdio transport abstraction simplifies deployment in subprocess and container environments +- Structured error logging provides clear diagnostic information for tool execution failures + +Negative: +- Dependency on @modelcontextprotocol/sdk couples the implementation to SDK versioning and maintenance +- Stdio transport limits communication to single-process or subprocess architectures +- Console.error logging may not integrate with structured logging systems or observability platforms +- Tool lookup using array find operations has O(n) complexity for large tool registries + +## Alternatives + +- Implement custom protocol without SDK dependency (rejected) + Rejected because: Custom protocol implementation would require maintaining protocol specification compliance, type definitions, and transport abstractions that the SDK provides, increasing maintenance burden and reducing interoperability + When valid: When protocol requirements diverge significantly from MCP specification or SDK introduces unacceptable performance overhead +- Use HTTP/REST API instead of stdio transport (rejected) + Rejected because: HTTP transport adds network layer complexity, authentication requirements, and deployment overhead compared to stdio subprocess model, while MCP SDK stdio transport meets current integration needs + When valid: When remote device access or multi-client concurrent access patterns are required +- Use structured logging library instead of console.error (deferred) + Rejected because: Console.error provides sufficient diagnostic information for current stdio-based deployment model + When valid: When integration with centralized logging systems or structured log analysis becomes a requirement + +## Risks + +- SDK version updates may introduce breaking changes to server initialization or type definitions + Mitigation: Pin SDK version in package.json and establish testing process for SDK upgrades before deployment + Owner: engineering team +- Stdio transport may not scale to high-frequency tool invocation patterns or large payload sizes + Mitigation: Establish performance benchmarks for tool execution and monitor stdio buffer utilization; plan migration to alternative transport if thresholds are exceeded + Owner: engineering team +- Console.error logging may not provide sufficient context for production debugging + Mitigation: Enhance error messages with contextual information (tool name, parameters, timestamps) and establish log aggregation process for stdio output + Owner: engineering team + +## Implementation Notes + +- Import server construction from @modelcontextprotocol/sdk/server/index.js and initialize with name 'android-device-mcp' and version metadata +- Import StdioServerTransport from @modelcontextprotocol/sdk/server/stdio.js and connect to server instance +- Import type definitions from @modelcontextprotocol/sdk/types.js for request/response message typing +- Implement tool error handling with console.error logging that includes tool name and error message +- Organize tool implementations in ./tools/ directory and validation utilities in ./utils/ directory for modularity + +## Continuation Context + + +Verify commands: +- grep -r "@modelcontextprotocol/sdk/server/index.js" --include="*.ts" --include="*.js" . +- grep -r "@modelcontextprotocol/sdk/server/stdio.js" --include="*.ts" --include="*.js" . +- grep -r "console.error.*Tool error" --include="*.ts" --include="*.js" . +- grep -r "capabilities.*tools" --include="*.ts" --include="*.js" . + +Accept when: +- All MCP server implementations import SDK modules from @modelcontextprotocol/sdk/server/index.js and stdio.js +- Server initialization includes capability declarations with tools support +- Tool error handling uses console.error with contextual information (tool name and error message) +- Type definitions from @modelcontextprotocol/sdk/types.js are used for protocol message typing + +## Enforcement + +- Verified by: Static analysis scanning for @modelcontextprotocol/sdk import statements +- Verified by: Code review verification of server initialization patterns and capability declarations +- Verified by: Automated testing of error logging output format and content +- Violation handling: CI pipeline fails if SDK imports are missing or incorrect +- Violation handling: Code review blocks merge if error handling does not follow console.error patterns +- Violation handling: Runtime monitoring alerts on tool execution failures without proper error logging +- Exception process: Document technical justification for alternative protocol or transport approach +- Exception process: Obtain architecture review approval for deviations from MCP SDK patterns +- Exception process: Update ADR with accepted exception and rationale \ No newline at end of file diff --git a/docs/adr/ed0c7f79-7808-4d5a-a55b-ee6ba89ae4d1-enforce-schema-based-input-validation-for-public-api-endpoints-schema-definitions-specify.md b/docs/adr/ed0c7f79-7808-4d5a-a55b-ee6ba89ae4d1-enforce-schema-based-input-validation-for-public-api-endpoints-schema-definitions-specify.md new file mode 100644 index 00000000000..c125634a12f --- /dev/null +++ b/docs/adr/ed0c7f79-7808-4d5a-a55b-ee6ba89ae4d1-enforce-schema-based-input-validation-for-public-api-endpoints-schema-definitions-specify.md @@ -0,0 +1,122 @@ +# Enforce Schema-Based Input Validation for Public API Endpoints: Schema Definitions Specify + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all public and external API endpoints that accept external input. + +## Context + +- Public API endpoints in the Android device server MCP tools (capture, tap-at) and GitHub automation scripts accept external input that requires validation before processing +- Multiple validation libraries are in use across the codebase: zod for TypeScript tool definitions and JSON parsing for Python configuration files +- Input validation occurs at API boundaries through schema.parse() calls in validation.ts and parser.parse() calls in xml.ts, establishing a consistent pattern of parse-time validation +- The codebase demonstrates 6 instances across TypeScript and Python modules where structured validation prevents malformed input from reaching core business logic +- External clients interact with these APIs through tool invocations and CI/CD workflows, requiring robust input validation to prevent injection attacks and runtime errors + +## Problem Statement + +Public API endpoints that accept external input without schema-based validation are vulnerable to malformed data, type errors, and potential security exploits. The absence of consistent validation patterns across API boundaries increases the risk of runtime failures and makes it difficult to enforce input contracts systematically. + +## Decision + +1. MUST: Schema definitions MUST specify type constraints, required fields, and acceptable value ranges using the validation library's type system (z.object, z.number, z.boolean, etc.) + +## Policy Block + +- MUST Schema definitions MUST specify type constraints, required fields, and acceptable value ranges using the validation library's type system (z.object, z.number, z.boolean, etc.) + +In scope: +- All MCP tool handlers that accept external parameters (capture, tap-at, and similar tools) +- GitHub automation scripts that parse JSON configuration files or accept command-line arguments +- XML parsing functions that process external UI hierarchy data +- Any API endpoint or function that accepts input from external clients, CI/CD systems, or user-provided data + +Out of scope: +- Internal function calls between trusted modules within the same service boundary +- Data transformations on already-validated data structures +- Test fixtures and mock data used exclusively in test environments +- Configuration files loaded at startup that are not user-modifiable + +Exceptions: +- EXC-001: Performance-critical hot paths where input has been validated upstream and re-validation would cause unacceptable latency +- EXC-002: Legacy endpoints scheduled for deprecation within the current quarter + +## Rationale + +- Evidence shows consistent use of schema validation across 6 files with 91.10% confidence, indicating an established architectural pattern rather than isolated instances +- The pattern uses industry-standard validation libraries (zod for TypeScript, json with schema validation for Python) that provide type safety and runtime validation +- Validation at API boundaries (parser.parse, schema.parse) creates a clear security perimeter that prevents malformed data from propagating through the system +- The pattern supports multiple input types (coordinates, booleans, XML documents, JSON configurations) demonstrating broad applicability across different API surfaces + +## Consequences + +Positive: +- Type safety and runtime validation prevent malformed input from causing runtime errors or security vulnerabilities in downstream components +- Declarative schema definitions serve as self-documenting API contracts that are easier to maintain than imperative validation code +- Early validation at API boundaries provides clear error messages to clients and reduces debugging time by failing fast +- Consistent validation patterns across TypeScript and Python codebases reduce cognitive load and make the validation approach predictable for developers + +Negative: +- Schema validation adds runtime overhead to every API call, though this is typically negligible compared to I/O operations +- Validation library dependencies (zod, fast-xml-parser) increase bundle size and create additional maintenance burden for security updates +- Complex validation rules may require custom validators that are harder to test and maintain than simple type checks +- Overly strict schemas can reject valid edge cases, requiring schema updates and potentially breaking existing clients + +## Alternatives + +- Manual validation using conditional checks and type guards without schema libraries (rejected) + Rejected because: Manual validation is error-prone, lacks composability, and does not provide the same level of type safety or maintainability as declarative schemas. Evidence shows the codebase has already standardized on schema-based validation. + When valid: Only for trivial single-parameter validations where schema library overhead is demonstrably excessive +- Runtime type checking using TypeScript decorators or Python type hints without explicit validation (rejected) + Rejected because: Type hints provide static analysis benefits but do not enforce runtime validation. TypeScript types are erased at runtime and Python type hints are not enforced without additional tooling. + When valid: As a complement to schema validation for improved IDE support and static analysis, not as a replacement +- API gateway-level validation using OpenAPI specifications or similar declarative formats (deferred) + Rejected because: Not rejected, but deferred pending evaluation of API gateway infrastructure. Would complement rather than replace application-level validation. + When valid: When API gateway infrastructure is available and can enforce OpenAPI specifications before requests reach application code + +## Risks + +- Validation library vulnerabilities (e.g., prototype pollution in fast-xml-parser) could compromise security despite validation being present + Mitigation: Maintain up-to-date dependencies, subscribe to security advisories for zod and fast-xml-parser, and run automated dependency scanning in CI/CD + Owner: Security team with engineering team support +- Inconsistent validation patterns between TypeScript (zod) and Python (json.load) could lead to validation gaps when porting code or maintaining cross-language consistency + Mitigation: Document validation patterns for both languages, establish code review guidelines to verify validation presence, and consider schema-sharing approaches like JSON Schema + Owner: Engineering team +- Performance degradation on high-throughput endpoints if validation schemas are complex or inefficiently structured + Mitigation: Profile validation performance on critical paths, optimize schemas for common cases, and consider caching parsed schemas or using faster validation libraries if needed + Owner: Engineering team + +## Implementation Notes + +- For TypeScript tools, define validation schemas using zod's z.object() with explicit types (z.number().int().nonnegative(), z.boolean().optional().default(value)) as demonstrated in capture.ts and tap-at.ts +- Use the validateInput utility function from utils/validation.ts to centralize validation logic and ensure consistent error handling across all tool handlers +- For Python scripts, use json.load() with subsequent schema validation or consider adopting a Python schema validation library (pydantic, marshmallow) for consistency with the TypeScript approach +- Document validation schemas alongside API documentation so clients understand input contracts and can anticipate validation errors + +## Continuation Context + + +Verify commands: +- grep -r 'z\.object\|schema\.parse\|validateInput' --include='*.ts' --include='*.js' src/tools/ | wc -l +- grep -r 'json\.load' --include='*.py' .github/scripts/ | wc -l +- npm test -- --grep 'validation' || python -m pytest -k validation + +Accept when: +- All tool handlers in src/tools/ use validateInput or equivalent schema validation before processing input parameters +- All Python scripts that parse external JSON use json.load with subsequent validation or a schema validation library +- Validation tests exist for each public API endpoint covering valid inputs, invalid inputs, and boundary conditions + +## Enforcement + +- Verified by: Code review checklist requiring validation presence for all new API endpoints +- Verified by: Automated linting rules that flag API handlers without schema validation +- Verified by: CI/CD pipeline tests that verify validation behavior for each endpoint +- Violation handling: Pull requests introducing API endpoints without validation are blocked until validation is added +- Violation handling: Existing violations are tracked in technical debt backlog with priority based on endpoint exposure and risk +- Violation handling: Security team is notified of validation gaps discovered in production endpoints +- Exception process: Request exception through architecture review board with justification and risk assessment +- Exception process: Document approved exceptions in code comments with reference to exception ID and approval date +- Exception process: Review exceptions quarterly to determine if they can be resolved or should be renewed \ No newline at end of file diff --git a/docs/adr/ed5f75c6-3d47-4881-8c46-b0fdccbde759-adopt-hilt-dependency-injection-for-android-application-components-application-class-use.md b/docs/adr/ed5f75c6-3d47-4881-8c46-b0fdccbde759-adopt-hilt-dependency-injection-for-android-application-components-application-class-use.md new file mode 100644 index 00000000000..a337cd3d778 --- /dev/null +++ b/docs/adr/ed5f75c6-3d47-4881-8c46-b0fdccbde759-adopt-hilt-dependency-injection-for-android-application-components-application-class-use.md @@ -0,0 +1,123 @@ +# Adopt Hilt Dependency Injection for Android Application Components: Application Class Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains 8 Android application components (Activities, Application, ViewModels) that require dependency injection for repositories, managers, and platform services +- AndroidX Activity and ViewModel components require lifecycle-aware dependency management with scoped instances +- The application architecture separates presentation logic (ViewModels) from Android framework components (Activities) requiring coordinated dependency graphs +- Multiple feature modules (authentication, autofill, credential provider) share common dependencies that must be consistently injected across component boundaries + +## Problem Statement + +Android application components require a standardized mechanism to inject dependencies such as repositories, managers, and platform services while respecting Android lifecycle constraints and component scopes. Manual dependency construction leads to boilerplate code, lifecycle management errors, and inconsistent dependency graphs across feature boundaries. + +## Decision + +1. MUST: Application class MUST use @Inject annotation for field injection of application-scoped dependencies + +## Policy Block + +- MUST Application class MUST use @Inject annotation for field injection of application-scoped dependencies + +In scope: +- All Activity subclasses (ComponentActivity, AppCompatActivity) +- All ViewModel implementations extending BaseViewModel +- Application class +- Repository and Manager classes requiring injection +- Feature modules: authentication, autofill, credential provider + +Out of scope: +- Composable functions (use parameter injection instead) +- Data classes and value objects +- Utility classes with static methods +- Third-party library components not designed for Hilt + +Exceptions: +- EXC-001: Legacy components during migration phase that have not yet been refactored + +## Rationale + +- Evidence shows consistent use of @AndroidEntryPoint across 4 Activity classes and @HiltViewModel across 3 ViewModel classes, indicating established pattern adoption +- The pattern enables lifecycle-aware dependency management required by Android components while maintaining separation between presentation and framework layers +- Hilt integration with AndroidX components (viewModels delegate, ComponentActivity) provides standardized scoping and reduces boilerplate for dependency graph construction +- Centralized dependency injection improves testability by enabling mock injection and reduces coupling between feature modules + +## Consequences + +Positive: +- Reduced boilerplate code for dependency instantiation and lifecycle management across 8 detected components +- Improved testability through constructor injection in ViewModels enabling easy mock substitution +- Consistent dependency graph management across feature boundaries (auth, autofill, credentials) +- Automatic lifecycle-aware scoping prevents memory leaks and improves resource management + +Negative: +- Increased build time due to annotation processing and code generation for dependency graphs +- Additional learning curve for developers unfamiliar with Hilt annotations and scoping rules +- Compile-time dependency on Hilt framework increases coupling to specific DI implementation +- Debugging dependency injection issues requires understanding generated code and component hierarchy + +## Alternatives + +- Manual dependency injection through factory patterns and service locators (rejected) + Rejected because: Requires significant boilerplate code, does not integrate with Android lifecycle, and increases risk of memory leaks through improper scope management + When valid: Small applications with fewer than 5 components and minimal dependency complexity +- Dagger 2 without Hilt Android extensions (rejected) + Rejected because: Requires manual component and module setup for each Android component, significantly more boilerplate than Hilt's @AndroidEntryPoint approach + When valid: Projects requiring fine-grained control over component hierarchy or supporting pre-AndroidX codebases +- Koin dependency injection framework (rejected) + Rejected because: Runtime dependency resolution increases risk of runtime errors compared to Hilt's compile-time validation, though offers simpler syntax + When valid: Kotlin-only projects prioritizing simplicity over compile-time safety + +## Risks + +- Annotation processing failures during build can cause cryptic compilation errors that are difficult to diagnose + Mitigation: Establish clear documentation for common Hilt errors, enable verbose annotation processing logs in CI, and maintain updated Hilt version + Owner: Engineering team +- Incorrect scope annotations can lead to memory leaks or premature dependency disposal + Mitigation: Implement code review checklist for scope validation, use LeakCanary in debug builds, and document scoping rules in architecture guide + Owner: Engineering team +- Migration of existing components to Hilt may introduce regressions if dependency initialization order changes + Mitigation: Migrate components incrementally with comprehensive integration tests, validate dependency graphs in staging environment before production deployment + Owner: Engineering team + +## Implementation Notes + +- Annotate all Activity classes with @AndroidEntryPoint and use @Inject for field injection of required dependencies +- Annotate all ViewModel classes with @HiltViewModel and use constructor injection with @Inject for all dependencies +- Use androidx.activity.viewModels() delegate in Activities to obtain Hilt-injected ViewModels with proper scoping +- Document dependency scope requirements (Singleton, ActivityScoped, ViewModelScoped) in module provider methods +- Ensure Application class is annotated with @HiltAndroidApp to initialize Hilt dependency graph + +## Continuation Context + + +Verify commands: +- grep -r '@AndroidEntryPoint' app/src/main/kotlin --include='*Activity.kt' | wc -l +- grep -r '@HiltViewModel' app/src/main/kotlin --include='*ViewModel.kt' | wc -l +- grep -r '@Inject' app/src/main/kotlin --include='*.kt' | grep -E '(constructor|lateinit var)' | wc -l +- ./gradlew assembleDebug --dry-run | grep 'Hilt' || echo 'Hilt not configured' + +Accept when: +- All Activity classes contain @AndroidEntryPoint annotation and compile successfully +- All ViewModel classes contain @HiltViewModel annotation with constructor injection +- Application builds without Hilt annotation processing errors +- Integration tests pass with injected dependencies functioning correctly across component lifecycle + +## Enforcement + +- Verified by: Static analysis via custom lint rules checking for @AndroidEntryPoint on Activity subclasses +- Verified by: Code review checklist validation for Hilt annotations on new components +- Verified by: CI build verification ensuring annotation processing completes without errors +- Verified by: Architecture tests validating ViewModel constructor injection patterns +- Violation handling: CI build fails if Activity classes lack @AndroidEntryPoint annotation +- Violation handling: Code review blocks merge if ViewModel classes use field injection instead of constructor injection +- Violation handling: Static analysis warnings escalated to errors for manual dependency instantiation in Hilt-enabled components +- Violation handling: Architecture test failures prevent deployment to staging environment +- Exception process: Submit exception request to architecture team with justification and migration timeline +- Exception process: Document exception in component-level comments with ADR reference and expiration date +- Exception process: Track exceptions in architecture decision log with quarterly review cycle +- Exception process: Require explicit approval from tech lead for exceptions lasting beyond one release cycle \ No newline at end of file diff --git a/docs/adr/f00636db-400f-40df-b081-6340fb4bdaa2-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-test-method-names.md b/docs/adr/f00636db-400f-40df-b081-6340fb4bdaa2-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-test-method-names.md new file mode 100644 index 00000000000..c00d169e1bc --- /dev/null +++ b/docs/adr/f00636db-400f-40df-b081-6340fb4bdaa2-standardize-unittest-and-vitest-as-test-frameworks-for-python-and-typescript-test-method-names.md @@ -0,0 +1,120 @@ +# Standardize unittest and vitest as Test Frameworks for Python and TypeScript: Test Method Names + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains test suites written in both Python and TypeScript, requiring language-appropriate testing frameworks for each ecosystem +- Python test files use unittest.TestCase classes with setUp/tearDown lifecycle methods and assertion methods like assertTrue, assertFalse, assertEqual, and assertIn +- TypeScript test files use vitest with describe/it block structure for organizing test cases and expectations +- Test files are located in distinct areas: Python tests in .github/scripts/validate-json/ and TypeScript tests in .claude/mcp/android-device-server/src/parsers/ +- Both frameworks provide standard test organization patterns: class-based with lifecycle hooks (unittest) and nested describe/it blocks (vitest) + +## Problem Statement + +The codebase requires consistent, language-appropriate testing frameworks to ensure test reliability, maintainability, and developer familiarity across Python and TypeScript components. Without standardized test frameworks, teams may introduce incompatible testing approaches, leading to fragmented tooling, inconsistent CI/CD integration, and increased cognitive overhead when switching between language contexts. + +## Decision + +1. SHOULD: Test method names SHOULD follow descriptive naming conventions that clearly indicate the behavior being tested (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) + +## Policy Block + +- SHOULD Test method names SHOULD follow descriptive naming conventions that clearly indicate the behavior being tested (e.g., test_validate_json_valid, test_find_duplicates_returns_empty_list_when_no_duplicates) + +In scope: +- All Python test files with test_ prefix or _test suffix +- All TypeScript test files with .spec.ts or .test.ts extensions +- Unit tests, integration tests, and functional tests in both languages +- Test fixtures and test utilities that support the primary test frameworks + +Out of scope: +- End-to-end tests that may use specialized frameworks like Playwright or Selenium +- Performance benchmarking tests that may use dedicated benchmarking libraries +- Property-based testing that may use hypothesis (Python) or fast-check (TypeScript) +- Test files in other languages not covered by this ADR + +Exceptions: +- EXC-001: Legacy test files written in pytest may remain unchanged if migration cost exceeds benefit and tests are stable +- EXC-002: Specialized testing scenarios require framework-specific features not available in unittest or vitest + +## Rationale + +- Evidence shows consistent usage of unittest in Python test files with standard TestCase patterns including setUp/tearDown lifecycle and assertion methods across 5 test functions +- Evidence shows vitest adoption in TypeScript with describe/it structure and standard imports from 'vitest' package, indicating established testing patterns +- Both frameworks are standard choices in their respective ecosystems: unittest is part of Python standard library, vitest is a modern Vite-native test runner with strong TypeScript support +- The pattern demonstrates 92.50% confidence across 2 files with clear framework-specific APIs and test organization patterns that indicate deliberate framework selection + +## Consequences + +Positive: +- Developers gain predictable test structure and familiar APIs when working within each language ecosystem +- CI/CD pipelines can standardize on framework-specific test runners and reporting formats +- Test tooling, IDE integrations, and debugging workflows become consistent within each language +- New team members can leverage existing framework knowledge and documentation from the broader community + +Negative: +- Teams must maintain knowledge of two different testing paradigms (class-based unittest vs. function-based vitest) +- Test patterns and idioms cannot be directly translated between Python and TypeScript codebases +- Framework-specific limitations constrain testing approaches (e.g., unittest lacks built-in parametrization without subtest) +- Migration from alternative frameworks (pytest, jest) requires test rewriting and potential loss of framework-specific features + +## Alternatives + +- Use pytest for Python testing instead of unittest (rejected) + Rejected because: Evidence shows established unittest patterns with TestCase classes, setUp/tearDown methods, and unittest-specific assertions. Migration would require rewriting existing tests and changing established patterns. + When valid: For new Python projects without existing unittest investment, pytest offers more concise syntax and better parametrization +- Use jest for TypeScript testing instead of vitest (rejected) + Rejected because: Evidence shows vitest adoption with describe/it patterns already in place. Jest and vitest have similar APIs, but vitest offers better Vite integration and faster execution for Vite-based projects. + When valid: For projects not using Vite or requiring jest-specific ecosystem plugins +- Standardize on a single cross-language testing approach using a unified framework (rejected) + Rejected because: No mature cross-language testing framework provides idiomatic support for both Python and TypeScript with comparable ecosystem integration and tooling support + When valid: Never valid for unit testing; may be appropriate for API contract testing or end-to-end testing scenarios + +## Risks + +- Developers unfamiliar with unittest may write tests using plain assert statements instead of unittest assertion methods, reducing test failure diagnostics quality + Mitigation: Provide linting rules to detect plain assert usage in unittest.TestCase classes and include unittest best practices in onboarding documentation + Owner: Engineering team +- Framework version updates may introduce breaking changes to test APIs or behavior, requiring test suite updates + Mitigation: Pin framework versions in dependency files, test framework upgrades in isolated branches, and maintain framework upgrade runbooks + Owner: DevOps and engineering team +- Specialized testing needs may not be well-supported by chosen frameworks, leading to workarounds or framework exceptions + Mitigation: Document exception process for specialized testing scenarios and evaluate complementary libraries (e.g., unittest.mock, vitest mocking) before seeking framework exceptions + Owner: Architecture review board + +## Implementation Notes + +- Python test files should import unittest and define test classes inheriting from unittest.TestCase with test methods prefixed with test_ +- TypeScript test files should import describe, it, and expect from 'vitest' and organize tests using nested describe blocks for logical grouping +- Use setUp/tearDown in Python for fixture management and beforeEach/afterEach in TypeScript for equivalent lifecycle management +- Follow naming conventions: descriptive test method names in Python (test__) and descriptive strings in TypeScript it() blocks +- Configure test discovery patterns in CI: Python unittest discovery with 'test_*.py' pattern and vitest configuration for '*.spec.ts' files + +## Continuation Context + + +Verify commands: +- grep -r 'import unittest' --include='test_*.py' .github/scripts/ +- grep -r 'from vitest import' --include='*.spec.ts' .claude/ +- grep -r 'class.*unittest\.TestCase' --include='test_*.py' . +- grep -r 'describe\|it' --include='*.spec.ts' . + +Accept when: +- All Python test files contain 'import unittest' and define classes inheriting from unittest.TestCase +- All TypeScript test files with .spec.ts extension import from 'vitest' and use describe/it structure +- Test execution in CI successfully runs unittest for Python tests and vitest for TypeScript tests with passing results + +## Enforcement + +- Verified by: CI pipeline test execution requiring unittest and vitest as test runners +- Verified by: Code review checklist verifying test framework compliance for new test files +- Verified by: Static analysis linting rules detecting non-compliant test patterns +- Violation handling: CI build fails if tests cannot be discovered or executed by the specified framework +- Violation handling: Code review blocks merge if test files use non-standard frameworks without documented exception +- Violation handling: Linting warnings flag plain assert usage in unittest.TestCase classes +- Exception process: Submit exception request to engineering lead with justification for alternative framework +- Exception process: Architecture review board evaluates exception for specialized testing scenarios +- Exception process: Approved exceptions documented in ADR addendum with scope and rationale \ No newline at end of file diff --git a/docs/adr/f02d043d-5823-4aeb-abfe-49a1db7895f6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-utilities-centralized.md b/docs/adr/f02d043d-5823-4aeb-abfe-49a1db7895f6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-utilities-centralized.md new file mode 100644 index 00000000000..8e1b8b6fed8 --- /dev/null +++ b/docs/adr/f02d043d-5823-4aeb-abfe-49a1db7895f6-adopt-schema-based-input-validation-with-zod-and-fast-xml-parser-validation-utilities-centralized.md @@ -0,0 +1,117 @@ +# Adopt Schema-Based Input Validation with zod and fast-xml-parser: Validation Utilities Centralized + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase processes external inputs from multiple sources including XML hierarchies, tool parameters, JSON configuration files, and command-line arguments +- Input validation requirements span type checking, range constraints, format validation, and structural parsing across TypeScript and Python modules +- The android-device-server MCP components expose public APIs (capture, tapAt, parseHierarchy) that accept user-provided coordinates, flags, and XML data requiring validation before processing +- GitHub automation scripts process untrusted inputs from pull request metadata, file paths, and JSON configuration requiring validation before label assignment and file operations +- The pattern emerged across 6 files with 91.10% confidence, indicating consistent adoption of declarative schema-based validation rather than imperative validation logic + +## Problem Statement + +Without standardized input validation, the codebase risks runtime errors from malformed data, security vulnerabilities from unvalidated external inputs, and inconsistent validation logic scattered across modules. The system requires a uniform approach to validate XML parsing, tool parameters, configuration files, and API inputs while maintaining type safety and clear error reporting. + +## Decision + +1. SHOULD: Validation utilities SHOULD be centralized in dedicated modules (e.g., utils/validation.ts) and reused across tool implementations + +## Policy Block + +- SHOULD Validation utilities SHOULD be centralized in dedicated modules (e.g., utils/validation.ts) and reused across tool implementations + +In scope: +- All tool handlers in android-device-server (capture.ts, tap-at.ts) +- XML parsing operations for UI hierarchy extraction (xml.ts) +- GitHub automation scripts processing PR metadata and JSON configs (label-pr.py, validate_json.py) +- Public API contracts exposed through ToolDefinition interfaces +- Command-line argument parsing using argparse + +Out of scope: +- Internal function parameters with compile-time type guarantees +- Data transformations on already-validated inputs +- Test fixtures and mock data generation +- Logging and debugging output formatting + +## Rationale + +- Schema-based validation with zod provides compile-time type inference and runtime validation in a single declaration, reducing duplication between TypeScript types and validation logic +- The fast-xml-parser library offers structured parsing with error handling for XML inputs, preventing injection attacks and malformed data from propagating through the UI hierarchy extraction pipeline +- Centralized validation in utils/validation.ts enables consistent error messages and reusable schema definitions across the 6 detected files, reducing maintenance burden +- The pattern demonstrates 91.10% confidence across multiple language contexts (TypeScript, Python), indicating architectural consensus on declarative validation over imperative checks + +## Consequences + +Positive: +- Type-safe validation with automatic TypeScript inference reduces runtime errors and improves IDE autocomplete for validated inputs +- Declarative schemas serve as self-documenting contracts for API boundaries, making input requirements explicit +- Consistent validation approach across TypeScript and Python modules reduces cognitive load for developers working across the codebase +- Early validation at API boundaries prevents invalid data from propagating deep into business logic, simplifying error handling + +Negative: +- Additional dependency on zod and fast-xml-parser increases bundle size and introduces external library maintenance burden +- Schema definitions require updates when API contracts change, adding a maintenance step beyond TypeScript type updates +- Runtime validation overhead adds latency to request processing, particularly for complex nested schemas +- Developers must learn zod API conventions and schema composition patterns, increasing onboarding complexity + +## Alternatives + +- Use imperative validation with manual type checks and if-statements for each parameter (rejected) + Rejected because: Imperative validation scatters validation logic across modules, lacks type inference, and requires manual synchronization between TypeScript types and runtime checks, increasing maintenance burden and error risk + When valid: For simple single-parameter validations in internal utility functions where schema overhead exceeds benefit +- Adopt class-validator with decorator-based validation on class properties (rejected) + Rejected because: Class-validator requires class instantiation and decorator metadata, adding complexity for simple function parameters; zod's functional approach better matches the codebase's tool handler pattern + When valid: In object-oriented codebases with persistent entity classes requiring validation across multiple lifecycle stages +- Use JSON Schema with ajv for validation across TypeScript and Python (rejected) + Rejected because: JSON Schema lacks TypeScript type inference and requires separate type definitions; zod provides superior developer experience with compile-time types derived from schemas + When valid: When validation schemas must be shared across multiple languages or serialized for external API documentation + +## Risks + +- Schema validation errors may expose internal implementation details through error messages, creating information disclosure vulnerabilities + Mitigation: Implement error sanitization layer that maps validation errors to generic user-facing messages while logging detailed errors internally + Owner: engineering team +- Complex nested schemas with recursive validation may introduce performance bottlenecks on high-frequency API endpoints + Mitigation: Profile validation overhead on critical paths and consider caching parsed schemas or implementing fast-path validation for common cases + Owner: engineering team +- Inconsistent validation between TypeScript (zod) and Python (json.load) may allow attacks that bypass one language's validation but not the other + Mitigation: Document validation requirements in language-agnostic terms and implement integration tests that verify equivalent validation behavior across language boundaries + Owner: engineering team + +## Implementation Notes + +- Define zod schemas adjacent to tool handler implementations using z.object() with explicit type constraints for all required and optional parameters +- Use the validateInput utility from utils/validation.ts to apply schemas consistently, ensuring uniform error handling across tool handlers +- For XML parsing, configure fast-xml-parser with appropriate options for attribute handling and text node parsing based on UI hierarchy requirements +- In Python modules, wrap json.load() calls in try-except blocks and validate required fields exist before accessing to prevent KeyError exceptions + +## Continuation Context + + +Verify commands: +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "parser\.parse(" .claude/mcp/android-device-server/src/parsers/ | wc -l +- grep -r "json\.load(" .github/scripts/ | wc -l +- npm test -- --testPathPattern=validation + +Accept when: +- All tool handlers in android-device-server define zod schemas with explicit type constraints before processing inputs +- XML parsing operations use fast-xml-parser with error handling for malformed input +- JSON configuration loading includes exception handling and validation of required fields +- Validation tests pass for boundary cases including negative numbers, missing optional fields, and malformed XML + +## Enforcement + +- Verified by: Code review checklist requiring zod schema definitions for new API endpoints and tool handlers +- Verified by: Static analysis with ESLint rules detecting unvalidated external inputs in TypeScript modules +- Verified by: Integration tests verifying validation error responses for invalid inputs across all public APIs +- Violation handling: Pull requests introducing new API endpoints without input validation schemas are blocked in code review +- Violation handling: Runtime validation errors are logged with request context for security monitoring and debugging +- Violation handling: Quarterly security audits identify unvalidated input paths and create remediation tickets +- Exception process: Exceptions require written justification documenting why alternative validation is sufficient for the specific use case +- Exception process: Security team review and approval for any API endpoint processing external input without schema validation +- Exception process: Approved exceptions are documented in code comments with links to approval decision and expiration review date \ No newline at end of file diff --git a/docs/adr/f12fda34-6c1a-45ce-937f-786fd0b3e6af-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-configuration-define-application.md b/docs/adr/f12fda34-6c1a-45ce-937f-786fd0b3e6af-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-configuration-define-application.md new file mode 100644 index 00000000000..f0e7e919ad2 --- /dev/null +++ b/docs/adr/f12fda34-6c1a-45ce-937f-786fd0b3e6af-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-configuration-define-application.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Configuration Define Application + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. SHOULD: Configuration SHOULD define application-specific labels (e.g., 'app:password-manager', 'app:authenticator') to enable component-level change tracking + +## Policy Block + +- SHOULD Configuration SHOULD define application-specific labels (e.g., 'app:password-manager', 'app:authenticator') to enable component-level change tracking + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/f2faca50-9c9e-4ea3-95ac-c41b960a4059-standardize-public-contract-functions-for-github-integration-automation-github-integration-scripts.md b/docs/adr/f2faca50-9c9e-4ea3-95ac-c41b960a4059-standardize-public-contract-functions-for-github-integration-automation-github-integration-scripts.md new file mode 100644 index 00000000000..e5e6db285c4 --- /dev/null +++ b/docs/adr/f2faca50-9c9e-4ea3-95ac-c41b960a4059-standardize-public-contract-functions-for-github-integration-automation-github-integration-scripts.md @@ -0,0 +1,99 @@ +# Standardize Public Contract Functions for GitHub Integration Automation: Github Integration Scripts + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains automation scripts for GitHub PR labeling that require structured interaction with GitHub APIs and configuration management +- Python scripts in .github/scripts/ implement integration logic using standard library modules (argparse, json, os, subprocess, sys) without external API client libraries +- The label-pr.py script exposes public contract functions (load_config_json, gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) that abstract GitHub CLI interactions +- Configuration-driven pattern matching against PR titles and file paths determines label application, requiring consistent data access patterns and input validation +- The automation boundary separates internal contract functions from external GitHub API calls via subprocess invocation of gh CLI + +## Problem Statement + +GitHub automation scripts require stable, testable internal APIs for configuration loading, GitHub data retrieval, and label manipulation, but ad-hoc function definitions without explicit contracts lead to inconsistent error handling, difficult testing, and fragile integration boundaries when scripts evolve or are reused across workflows. + +## Decision + +1. MUST: GitHub integration scripts MUST expose public contract functions with explicit names following the pattern: load_config_json, gh_get_*, gh_add_*, gh_replace_* for configuration, retrieval, and mutation operations respectively + +## Policy Block + +- MUST GitHub integration scripts MUST expose public contract functions with explicit names following the pattern: load_config_json, gh_get_*, gh_add_*, gh_replace_* for configuration, retrieval, and mutation operations respectively + +## Rationale + +- The detected pattern shows consistent naming conventions (gh_* prefix) and explicit public contracts in label-pr.py, indicating intentional API design for internal reuse and testing +- Using subprocess with gh CLI rather than direct API clients reduces dependency complexity and leverages GitHub's official CLI for authentication and API versioning +- Explicit exception handling for JSON parsing and pattern matching demonstrates defensive programming at integration boundaries where external configuration drives behavior +- Set-based label manipulation (.add() operations) prevents duplicate labels and provides efficient membership testing for conditional logic + +## Consequences + +Positive: +- Clear function contracts enable unit testing of GitHub integration logic without requiring live API access or complex mocking +- Standardized naming conventions (gh_* prefix) make integration boundaries explicit and improve code discoverability +- Subprocess-based gh CLI invocation isolates authentication complexity and API versioning from script logic +- Configuration-driven pattern matching allows non-developers to modify labeling rules without code changes + +Negative: +- Subprocess invocation of gh CLI adds latency and process overhead compared to direct HTTP API calls +- Reliance on gh CLI availability creates an external dependency that must be present in CI/CD environments +- Standard library-only constraint limits access to advanced HTTP features like connection pooling, retry logic, and structured error responses +- Set-based label manipulation requires conversion overhead when interfacing with list-based GitHub API responses + +## Alternatives + +- Use PyGithub or github3.py library for direct GitHub API access with native Python objects (rejected) + Rejected because: Introduces external dependency management complexity and requires explicit authentication token handling, whereas gh CLI provides authenticated context automatically in GitHub Actions + When valid: When scripts run outside GitHub Actions environment or require advanced API features not exposed by gh CLI +- Implement inline GitHub API calls without abstraction functions (rejected) + Rejected because: Reduces testability and code reuse, making it difficult to mock external dependencies or refactor integration logic independently + When valid: For one-off scripts with no reuse requirements and no testing needs +- Create a formal Python package with typed interfaces for GitHub integration contracts (deferred) + Rejected because: Current evidence shows single-file script usage without cross-repository reuse patterns that would justify packaging overhead + When valid: When GitHub integration patterns are reused across multiple repositories or require versioned distribution + +## Risks + +- gh CLI command interface changes could break subprocess invocations without compile-time detection + Mitigation: Pin gh CLI version in CI environment and add integration tests that verify command output format + Owner: engineering team +- Configuration JSON schema drift could cause runtime failures if validation is insufficient + Mitigation: Implement explicit schema validation for required keys (title_patterns, path_patterns) with clear error messages + Owner: engineering team +- Subprocess error handling may not capture all gh CLI failure modes (network errors, rate limits, authentication failures) + Mitigation: Wrap subprocess calls with comprehensive exception handling and log stderr output for debugging + Owner: engineering team + +## Implementation Notes + +- Prefix all GitHub API interaction functions with 'gh_' to clearly mark integration boundary and distinguish from internal helper functions +- Use json.load() with explicit exception handling (try/except json.JSONDecodeError) for all configuration file parsing +- Implement label manipulation using Python sets for deduplication, converting to lists only when calling gh CLI commands +- Structure subprocess calls to capture both stdout and stderr, logging errors with context about which gh command failed + +## Continuation Context + + +Verify commands: +- grep -E '(load_config_json|gh_get_|gh_add_|gh_replace_)' .github/scripts/*.py +- grep -E 'except.*json\.JSONDecodeError' .github/scripts/*.py +- grep -E 'subprocess\.(run|check_output|Popen).*gh ' .github/scripts/*.py + +Accept when: +- All GitHub integration functions follow naming convention (load_config_json, gh_*) and are discoverable via grep +- JSON parsing includes explicit exception handling for JSONDecodeError in configuration loading functions +- GitHub API interactions use subprocess invocation of gh CLI rather than direct HTTP client libraries + +## Enforcement + +- Verified by: Code review checklist verifying function naming conventions and exception handling patterns +- Verified by: Automated grep-based verification in CI pipeline checking for required function prefixes and error handling +- Violation handling: PR comments requesting refactoring to match established naming conventions +- Violation handling: CI pipeline warnings when new GitHub integration functions lack proper error handling +- Exception process: Document rationale in code comments when alternative patterns are necessary +- Exception process: Obtain approval from platform team for deviations from standard contract patterns \ No newline at end of file diff --git a/docs/adr/f44a5164-24d3-4b66-8385-c0f71dfc3f0b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-automation-scripts-load.md b/docs/adr/f44a5164-24d3-4b66-8385-c0f71dfc3f0b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-automation-scripts-load.md new file mode 100644 index 00000000000..d704e40976e --- /dev/null +++ b/docs/adr/f44a5164-24d3-4b66-8385-c0f71dfc3f0b-adopt-pattern-based-label-assignment-for-external-client-boundaries-in-pr-automation-automation-scripts-load.md @@ -0,0 +1,117 @@ +# Adopt Pattern-Based Label Assignment for External Client Boundaries in PR Automation: Automation Scripts Load + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains a PR labeling automation script (.github/scripts/label-pr.py) that processes pull requests by matching title and path patterns against configuration-driven rules +- The script uses argparse, json, os, subprocess, and sys to coordinate GitHub API interactions and label management operations +- Label assignment logic evaluates both title_patterns and path_patterns from configuration, applying labels conditionally based on matches (e.g., 'app:password-manager', 'app:authenticator') +- The pattern demonstrates boundary testing strategy where external client interactions (GitHub PR workflow) are validated through pattern matching and automated classification +- JSON configuration loading (json.load) and exception handling (except json) indicate a data-driven approach to defining test boundaries and classification rules + +## Problem Statement + +Pull request automation workflows require consistent, testable mechanisms for classifying changes and applying labels based on both metadata (titles) and structural changes (file paths), but manual label assignment is error-prone and lacks systematic validation of external client boundary interactions with the CI/CD pipeline. + +## Decision + +1. MUST: PR automation scripts MUST load label classification rules from JSON configuration files using json.load to enable data-driven pattern matching + +## Policy Block + +- MUST PR automation scripts MUST load label classification rules from JSON configuration files using json.load to enable data-driven pattern matching + +In scope: +- PR automation scripts in .github/scripts/ directory +- JSON configuration files defining title_patterns and path_patterns +- GitHub API wrapper functions (gh_* prefix) +- Label assignment logic for application and component classification +- CI/CD workflows that trigger PR labeling automation + +Out of scope: +- Manual label assignment through GitHub UI +- Label assignment in issue tracking (non-PR contexts) +- Runtime application labeling or tagging +- Deployment environment labels or tags +- Container or infrastructure labeling systems + +## Rationale + +- The evidence shows a systematic approach to testing external client boundaries by automating PR classification through pattern matching, reducing manual errors and ensuring consistent label application +- Configuration-driven pattern matching (title_patterns, path_patterns) enables declarative definition of test boundaries and validation rules without code changes +- Encapsulation of GitHub API interactions in dedicated functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) creates testable boundaries for external client integration +- The pattern supports testing strategy by making PR workflow behavior predictable, auditable, and verifiable through configuration inspection + +## Consequences + +Positive: +- Automated label assignment reduces manual effort and human error in PR classification +- Configuration-driven approach enables non-developers to modify labeling rules without code changes +- Encapsulated GitHub API functions provide clear testing boundaries and enable mocking in unit tests +- Pattern matching on both titles and paths provides comprehensive change classification coverage + +Negative: +- Configuration complexity increases as the number of patterns and labels grows +- Pattern matching logic may become brittle if PR title conventions are not consistently followed +- Dependency on subprocess and GitHub API introduces external failure modes that require error handling +- JSON configuration parsing errors can silently fail if exception handling is not comprehensive + +## Alternatives + +- Use GitHub Actions marketplace actions for PR labeling instead of custom Python scripts (rejected) + Rejected because: Marketplace actions lack the specific pattern matching flexibility and configuration structure required for multi-faceted classification (title + path patterns with application-specific labels) + When valid: When labeling requirements are simple and covered by existing marketplace actions with minimal customization needs +- Implement labeling logic directly in GitHub Actions workflow YAML using conditional expressions (rejected) + Rejected because: YAML-based conditional logic becomes unmaintainable for complex pattern matching and lacks structured configuration management capabilities + When valid: When labeling rules are extremely simple (e.g., single path prefix matching) and unlikely to change frequently +- Use CODEOWNERS file for automatic label assignment based on file ownership (deferred) + Rejected because: CODEOWNERS provides ownership mapping but does not support title pattern matching or flexible label classification beyond team assignment + When valid: When label assignment should be strictly based on code ownership rather than change content or PR metadata + +## Risks + +- JSON configuration schema drift may cause runtime errors if pattern structure changes without corresponding code updates + Mitigation: Implement JSON schema validation and unit tests that verify configuration structure before pattern matching execution + Owner: engineering team +- GitHub API rate limiting or authentication failures may cause label assignment to fail silently or incompletely + Mitigation: Add retry logic with exponential backoff and explicit error logging for all GitHub API interactions + Owner: engineering team +- Pattern matching false positives may apply incorrect labels, causing confusion in PR triage and routing + Mitigation: Implement dry-run mode for testing pattern changes and maintain audit logs of label assignments with pattern match details + Owner: engineering team + +## Implementation Notes + +- Create JSON configuration schema with title_patterns and path_patterns arrays, each containing regex or glob patterns mapped to label names +- Implement load_config_json function with try-except block for json.JSONDecodeError to handle malformed configuration gracefully +- Define GitHub API wrapper functions (gh_get_changed_files, gh_get_pr_title, gh_add_labels, gh_replace_labels) using subprocess or GitHub REST API client +- Use Python sets for label collection to automatically deduplicate labels before applying to PR +- Add logging statements at key decision points (pattern matches, label additions) to enable debugging and audit trail + +## Continuation Context + + +Verify commands: +- grep -r 'json.load' .github/scripts/ | grep -q 'label-pr.py' +- grep -E '(gh_get_changed_files|gh_get_pr_title|gh_add_labels|gh_replace_labels)' .github/scripts/label-pr.py +- python3 -m py_compile .github/scripts/label-pr.py && echo 'Syntax valid' + +Accept when: +- The label-pr.py script successfully loads JSON configuration and contains exception handling for json parsing errors +- All GitHub API interactions are encapsulated in dedicated functions with gh_ prefix +- The script evaluates both title_patterns and path_patterns from configuration to determine label assignment + +## Enforcement + +- Verified by: Code review of PR automation scripts in .github/scripts/ +- Verified by: CI pipeline validation that executes label-pr.py on test PRs +- Verified by: JSON schema validation tests for configuration files +- Violation handling: PR labeling failures trigger workflow warnings visible in GitHub Actions logs +- Violation handling: Configuration validation errors block PR automation workflow execution +- Violation handling: Manual label review required when automated assignment fails or produces unexpected results +- Exception process: Document exceptional cases requiring manual label override in PR comments +- Exception process: Maintain exception log in configuration repository with rationale for pattern bypasses +- Exception process: Review exceptions quarterly to identify patterns that should be codified in configuration \ No newline at end of file diff --git a/docs/adr/f5e43e08-8bf6-4b41-a34c-4721ee14a1b4-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md b/docs/adr/f5e43e08-8bf6-4b41-a34c-4721ee14a1b4-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md new file mode 100644 index 00000000000..26dd6640b6f --- /dev/null +++ b/docs/adr/f5e43e08-8bf6-4b41-a34c-4721ee14a1b4-adopt-jetpack-compose-composable-annotation-for-ui-component-declaration-composable-functions-use.md @@ -0,0 +1,123 @@ +# Adopt Jetpack Compose @Composable Annotation for UI Component Declaration: Composable Functions Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all UI component development in the Android application codebase. + +## Context + +- The Android application uses Jetpack Compose as the declarative UI framework, requiring the @Composable annotation to mark functions that emit UI elements +- Three screen implementation files in the auth feature module (SetupUnlockScreen.kt, ExpiredRegistrationLinkScreen.kt, CompleteRegistrationHandler.kt) consistently use @Composable functions with androidx.compose.* foundation and runtime libraries +- The codebase demonstrates a pattern of composing UI hierarchies using androidx.compose.foundation.layout components (Column, Row, Spacer) and androidx.compose.runtime utilities (remember, Composable) +- The detection spans authentication-related UI screens, indicating organization-wide adoption of Compose for user-facing interface construction + +## Problem Statement + +Android UI development requires a consistent framework for declaring composable UI components that integrate with the Jetpack Compose runtime, ensuring proper recomposition behavior, state management, and layout composition across all screen implementations. + +## Decision + +1. MAY: Composable functions MAY use androidx.activity.compose utilities (e.g., BackHandler) for platform integration when appropriate + +## Policy Block + +- MAY Composable functions MAY use androidx.activity.compose utilities (e.g., BackHandler) for platform integration when appropriate + +In scope: +- All Android UI screen implementations in app/src/main/kotlin UI packages +- Authentication feature module UI components +- Any function that directly or indirectly emits Compose UI elements +- Handler components that coordinate UI composition with ViewModels + +Out of scope: +- ViewModel classes and business logic layers +- Data repository and network layer implementations +- Utility functions that do not emit UI +- Android View system components (legacy XML-based UI) +- Unit test files and test utilities + +Exceptions: +- EXC-001: Interoperating with legacy Android View system components during migration +- EXC-002: Preview functions for Android Studio Compose preview tooling + +## Rationale + +- Evidence from 3 files shows consistent use of @Composable annotation with 92.50% confidence, indicating established organizational practice +- Jetpack Compose provides declarative UI construction with automatic recomposition, reducing boilerplate and state synchronization complexity compared to imperative View system +- The androidx.compose.foundation and androidx.compose.runtime libraries form the core dependency set observed across all detected files, establishing a stable API surface +- Standardizing on @Composable annotation ensures compile-time verification of composable function constraints and enables Compose compiler optimizations + +## Consequences + +Positive: +- Declarative UI composition reduces state management complexity and eliminates manual view updates +- Compose compiler enforces composable function constraints at compile-time, catching errors early +- Consistent use of androidx.compose.* libraries provides a unified API surface for UI development +- Improved developer productivity through reduced boilerplate and better tooling support (preview, inspection) + +Negative: +- Requires learning curve for developers familiar with traditional Android View system +- Increases APK size due to Compose runtime library dependencies +- Limited interoperability with legacy View-based components requires AndroidView wrappers +- Compose compiler plugin adds build time overhead for annotation processing + +## Alternatives + +- Continue using traditional Android View system with XML layouts and findViewById (rejected) + Rejected because: Imperative View system requires manual state synchronization, increases boilerplate, and lacks compile-time UI verification. Evidence shows organization has already committed to Compose. + When valid: Only for legacy modules not yet migrated or when specific View components have no Compose equivalent +- Adopt alternative declarative UI frameworks (Flutter, React Native) (rejected) + Rejected because: Would require complete platform rewrite and abandonment of native Android tooling. Evidence shows deep integration with androidx.compose.* libraries. + When valid: For new greenfield projects with cross-platform requirements from inception +- Hybrid approach mixing Compose and View system components (deferred) + Rejected because: Not rejected but deferred as a migration strategy. Evidence shows pure Compose adoption in detected files. + When valid: During migration period for legacy screens not yet converted to Compose + +## Risks + +- Compose API instability or breaking changes in androidx.compose.* libraries during version upgrades + Mitigation: Pin Compose library versions in dependency management, test thoroughly before upgrading, monitor Compose release notes + Owner: Android platform team +- Performance degradation from excessive recomposition in complex UI hierarchies + Mitigation: Use remember, derivedStateOf, and key() appropriately, profile with Compose Layout Inspector, follow Compose performance best practices + Owner: Engineering team +- Developer knowledge gap leading to anti-patterns or misuse of Composable functions + Mitigation: Provide Compose training, establish code review guidelines, create internal documentation and examples + Owner: Engineering team and tech leads + +## Implementation Notes + +- Import androidx.compose.runtime.Composable explicitly in all UI component files +- Use androidx.compose.foundation.layout components (Column, Row, Spacer, Box) as primary layout primitives +- Integrate androidx.compose.runtime.remember for state that should survive recomposition +- Follow naming convention of PascalCase for Composable functions to distinguish from regular functions +- Separate Composable UI functions from ViewModel and business logic to maintain clear architectural boundaries + +## Continuation Context + + +Verify commands: +- grep -r '@Composable' app/src/main/kotlin --include='*.kt' | wc -l +- grep -r 'import androidx.compose.runtime.Composable' app/src/main/kotlin --include='*.kt' | wc -l +- find app/src/main/kotlin -name '*Screen.kt' -exec grep -L '@Composable' {} \; + +Accept when: +- All UI screen files (matching *Screen.kt pattern) contain at least one @Composable annotated function +- Grep for @Composable annotation returns matches proportional to UI component count (minimum 3 files as per evidence) +- No UI component files emit visual elements without @Composable annotation (verify via static analysis or code review) + +## Enforcement + +- Verified by: Automated static analysis via Compose compiler checks during build +- Verified by: Code review checklist requiring @Composable annotation for UI functions +- Verified by: CI pipeline grep verification counting @Composable usage in UI packages +- Violation handling: Build failure if Composable functions violate compiler constraints (e.g., calling composables from non-composable context) +- Violation handling: Code review rejection for UI functions missing @Composable annotation +- Violation handling: Automated linting warnings for missing androidx.compose.runtime.Composable imports +- Exception process: Submit exception request to architecture team with justification for non-Compose UI approach +- Exception process: Document legacy View system usage in migration tracking system +- Exception process: Obtain approval from tech lead for interop scenarios requiring AndroidView wrappers \ No newline at end of file diff --git a/docs/adr/f8f48f71-1510-4000-84be-9e9f3a16e0d9-adopt-zod-schema-validation-for-tool-input-parameters-tool-implementations-import.md b/docs/adr/f8f48f71-1510-4000-84be-9e9f3a16e0d9-adopt-zod-schema-validation-for-tool-input-parameters-tool-implementations-import.md new file mode 100644 index 00000000000..43721e8145c --- /dev/null +++ b/docs/adr/f8f48f71-1510-4000-84be-9e9f3a16e0d9-adopt-zod-schema-validation-for-tool-input-parameters-tool-implementations-import.md @@ -0,0 +1,116 @@ +# Adopt Zod Schema Validation for Tool Input Parameters: Tool Implementations Import + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all tool implementations in the Android Device Server MCP that accept external input parameters. + +## Context + +- The Android Device Server MCP exposes tool handlers that accept external input from clients, requiring validation to prevent invalid operations and runtime errors +- Tool parameters include coordinates, timing values, and boolean flags that must conform to specific constraints (non-negative integers, minimum values, type safety) +- The codebase imports 'zod' as a core dependency and '../utils/validation.js' across multiple tool implementations, indicating a standardized validation approach +- Two tool handlers (capture.ts and tap-at.ts) demonstrate consistent schema definition patterns using z.object() with typed field validators + +## Problem Statement + +Tool handlers in the Android Device Server MCP must validate external input parameters to ensure type safety, enforce domain constraints (e.g., non-negative coordinates, valid timing ranges), and prevent invalid ADB commands from being executed, but without a standardized validation approach, each tool would implement ad-hoc validation logic leading to inconsistency and maintenance burden. + +## Decision + +1. MUST: Tool implementations MUST import validation utilities from '../utils/validation.js' for consistent error handling + +## Policy Block + +- MUST Tool implementations MUST import validation utilities from '../utils/validation.js' for consistent error handling + +In scope: +- All tool handler implementations in src/tools/ that accept external parameters +- Input validation for ADB command parameters (coordinates, timing, flags) +- Public API contracts exposed through MCP tool interfaces + +Out of scope: +- Internal utility functions that do not accept external input +- ADB command output parsing and response formatting +- Device discovery and connection management logic + +## Rationale + +- The evidence shows consistent use of Zod schemas across capture.ts and tap-at.ts with identical import patterns ('zod', '../utils/validation.js'), indicating an established validation standard +- Schema definitions enforce domain-specific constraints (non-negative coordinates, minimum timing values) that prevent invalid ADB commands and improve system reliability +- Centralized validation through Zod provides type inference, runtime validation, and clear error messages, reducing boilerplate and improving developer experience +- The pattern appears in the security.input_validation facet with 91.20% confidence across 2 files, demonstrating measurable adoption + +## Consequences + +Positive: +- Type-safe input validation with automatic TypeScript type inference from schemas +- Consistent validation error messages and handling across all tool implementations +- Reduced boilerplate code compared to manual parameter checking and validation +- Clear API contracts that are self-documenting through schema definitions + +Negative: +- Additional runtime overhead for schema validation on every tool invocation +- Dependency on the Zod library increases bundle size and introduces external maintenance risk +- Developers must learn Zod API and schema composition patterns +- Schema definitions add verbosity to tool handler implementations + +## Alternatives + +- Manual parameter validation using TypeScript type guards and conditional checks (rejected) + Rejected because: Leads to inconsistent validation logic, verbose boilerplate, and no runtime type safety guarantees + When valid: For simple internal functions with minimal validation requirements +- Use JSON Schema with ajv validator for runtime validation (rejected) + Rejected because: Requires separate type definitions and schema definitions, losing TypeScript type inference benefits + When valid: When interoperating with systems that already use JSON Schema standards +- Use io-ts for functional programming style validation (rejected) + Rejected because: Steeper learning curve and more verbose syntax compared to Zod's developer-friendly API + When valid: In codebases with strong functional programming conventions using fp-ts + +## Risks + +- Zod library vulnerabilities or breaking changes in future versions could impact all tool handlers + Mitigation: Pin Zod version in package.json, monitor security advisories, and maintain comprehensive test coverage for validation logic + Owner: engineering team +- Complex nested schemas may introduce performance bottlenecks for high-frequency tool invocations + Mitigation: Profile validation performance, cache parsed schemas, and consider lazy validation for optional deep structures + Owner: engineering team +- Inconsistent schema patterns across tools if validation utilities are not properly documented + Mitigation: Document standard validation patterns in ../utils/validation.js, provide schema templates, and enforce through code review + Owner: engineering team + +## Implementation Notes + +- Import Zod and validation utilities at the top of each tool handler: import { z } from 'zod' and import validation utilities from '../utils/validation.js' +- Define the input schema as a const using z.object() with appropriate field validators before the handler function +- Use .int().nonnegative() for coordinate parameters, .min(0) for timing parameters, and .optional().default() for optional flags +- Pass the schema to the validation utility to parse and validate input, handling validation errors with clear messages +- Export the inferred TypeScript type using z.infer for use in function signatures and documentation + +## Continuation Context + + +Verify commands: +- grep -r "from 'zod'" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "z\.object({" .claude/mcp/android-device-server/src/tools/ | wc -l +- grep -r "../utils/validation" .claude/mcp/android-device-server/src/tools/ | wc -l + +Accept when: +- All tool handlers in src/tools/ that accept external parameters import 'zod' and define validation schemas +- Grep commands show consistent usage of z.object() schema definitions across tool implementations +- Validation utility imports from '../utils/validation.js' are present in all relevant tool files + +## Enforcement + +- Verified by: Code review checklist requiring Zod schema validation for new tool handlers +- Verified by: Automated grep-based checks in CI pipeline verifying presence of validation imports +- Verified by: TypeScript compilation ensuring type safety through schema inference +- Violation handling: Pull requests adding tool handlers without Zod validation are rejected during code review +- Violation handling: CI pipeline fails if tool files lack required validation imports +- Violation handling: Runtime errors from unvalidated input are treated as P1 bugs requiring immediate remediation +- Exception process: Exceptions require written justification documenting why Zod validation is inappropriate for the specific use case +- Exception process: Alternative validation approach must be proposed and approved by tech lead +- Exception process: Exception is documented in code comments with reference to approval decision \ No newline at end of file diff --git a/docs/adr/f91ae19b-2748-445b-8617-0fb6a06e5b19-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-body.md b/docs/adr/f91ae19b-2748-445b-8617-0fb6a06e5b19-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-body.md new file mode 100644 index 00000000000..3fcd646259f --- /dev/null +++ b/docs/adr/f91ae19b-2748-445b-8617-0fb6a06e5b19-standardize-http-error-response-testing-with-junit-5-and-okhttp-mock-responses-error-response-body.md @@ -0,0 +1,117 @@ +# Standardize HTTP Error Response Testing with JUnit 5 and OkHttp Mock Responses: Error Response Body + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Network error handling requires consistent testing patterns to validate error response parsing and exception mapping behavior +- The codebase uses custom exception types (CookieRedirectException, LocalNetworkAccessException) that must be converted to BitwardenError types with specific HTTP status codes +- OkHttp's Response.error() and ResponseBody.toResponseBody() provide a standard mechanism for creating mock HTTP error responses in unit tests +- JUnit 5 (@Test annotations) serves as the testing framework with assertion methods (assertEquals, assertTrue) for validating error transformation logic +- Error response bodies contain structured JSON with message and validationErrors fields that must be parsed and validated in test scenarios + +## Problem Statement + +Network layer error handling involves complex transformations between HTTP responses, custom exceptions, and domain error types. Without standardized testing patterns for error scenarios, teams may create inconsistent mock responses, fail to validate critical error parsing paths, or miss edge cases in exception-to-error mappings. This leads to fragile error handling code and potential runtime failures when unexpected HTTP error responses occur. + +## Decision + +1. MUST: Error response body parsing tests MUST use assertEquals to validate extracted message and validationErrors fields + +## Policy Block + +- MUST Error response body parsing tests MUST use assertEquals to validate extracted message and validationErrors fields + +In scope: +- Network layer unit tests in network/src/test/kotlin/**/*Test.kt +- Tests validating toBitwardenError() extension functions +- Tests validating parseErrorBodyOrNull() error parsing logic +- HTTP error response mocking for status codes 400-599 +- Custom exception type testing (CookieRedirectException, LocalNetworkAccessException) + +Out of scope: +- Integration tests with real HTTP clients +- End-to-end error handling flows +- UI layer error display testing +- Non-HTTP error scenarios (e.g., network timeouts, SSL errors) +- Production error logging implementation + +## Rationale + +- The evidence shows consistent use of Response.error() and toResponseBody() across 2 test files, indicating an established pattern for mocking HTTP error responses +- JUnit 5 assertions (assertEquals, assertTrue) provide type-safe validation of error transformations with clear failure messages +- Testing both exception-to-error mapping and JSON body parsing ensures comprehensive coverage of the error handling pipeline +- The pattern enables isolated unit testing of error logic without requiring actual network calls or HTTP server infrastructure + +## Consequences + +Positive: +- Consistent error response mocking reduces test code duplication and improves maintainability +- Type-safe assertions catch regressions in error transformation logic during refactoring +- Isolated unit tests execute quickly without network dependencies, enabling fast feedback loops +- Structured JSON validation ensures error messages and validation errors are correctly extracted for user display + +Negative: +- OkHttp-specific mocking creates tight coupling between tests and the HTTP client library +- Mock responses may diverge from actual server error formats if not kept synchronized +- Test coverage is limited to known error scenarios and may miss unexpected server responses +- Additional test code is required to maintain comprehensive error scenario coverage + +## Alternatives + +- Use MockWebServer to simulate full HTTP server responses for error testing (rejected) + Rejected because: MockWebServer adds complexity and slower test execution for unit-level error transformation logic that can be tested with simple mock objects + When valid: Integration tests requiring full request/response cycles with headers, redirects, and connection handling +- Create custom test fixtures or builders for BitwardenError instances (rejected) + Rejected because: Direct construction bypasses the actual transformation logic (toBitwardenError) that needs validation, reducing test coverage of production code paths + When valid: Tests focused on error handling behavior downstream of error creation, where the transformation itself is not under test +- Use property-based testing to generate random error responses (deferred) + Rejected because: Not currently implemented in the codebase; would require additional testing framework dependencies + When valid: Future enhancement to discover edge cases in error parsing logic with generated inputs + +## Risks + +- Mock error responses diverge from actual server API error formats over time + Mitigation: Maintain contract tests or API schema validation to ensure mock responses match production error formats; periodically review server API documentation + Owner: Network layer team +- OkHttp library updates may change Response.error() behavior or deprecate APIs + Mitigation: Pin OkHttp version in dependency management; review release notes during upgrades; maintain adapter layer if API changes + Owner: Engineering team +- Test coverage gaps for uncommon HTTP status codes or malformed response bodies + Mitigation: Use code coverage tools to identify untested error paths; add parameterized tests for status code ranges; include malformed JSON test cases + Owner: QA and development team + +## Implementation Notes + +- Import okhttp3.ResponseBody.Companion.toResponseBody and retrofit2.Response for creating mock error responses in test setup +- Structure test methods with clear arrange-act-assert phases: create exception/response, call transformation method, validate result with assertions +- Use trimIndent() for multi-line JSON response bodies to improve test readability and maintainability +- Group related error tests in dedicated test classes (e.g., BitwardenErrorTest for exception mappings, ExceptionExtensionsTest for parsing logic) +- Include both positive cases (successful error parsing) and negative cases (missing fields, malformed JSON) in test suites + +## Continuation Context + + +Verify commands: +- grep -r "Response.error" network/src/test/kotlin/ | wc -l +- grep -r "@Test" network/src/test/kotlin/com/bitwarden/network/ | grep -E "(BitwardenError|Exception)" | wc -l +- grep -r "assertEquals\|assertTrue" network/src/test/kotlin/com/bitwarden/network/model/ network/src/test/kotlin/com/bitwarden/network/util/ | wc -l + +Accept when: +- At least 2 test files use Response.error() with toResponseBody() for HTTP error mocking +- All custom exception types have corresponding @Test methods validating toBitwardenError() transformations +- Error parsing tests include assertEquals assertions for both message and validationErrors fields + +## Enforcement + +- Verified by: Code review checklist requiring error transformation tests for new exception types +- Verified by: CI pipeline test execution with minimum coverage thresholds for network error handling code +- Verified by: Static analysis to detect Response.error() usage patterns in test files +- Violation handling: Pull requests adding new error types without corresponding tests are blocked until tests are added +- Violation handling: Coverage drops in network error handling modules trigger build warnings and team notifications +- Violation handling: Quarterly audit of error test patterns identifies inconsistencies for remediation +- Exception process: Temporary exception granted for prototype or spike work with technical debt ticket created +- Exception process: Exception requires architecture team approval with documented rationale +- Exception process: All exceptions reviewed in monthly technical debt review meetings with remediation timeline \ No newline at end of file diff --git a/docs/adr/facaccf3-6586-4106-b5ac-4ada57f5feb2-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-tool-error-logs.md b/docs/adr/facaccf3-6586-4106-b5ac-4ada57f5feb2-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-tool-error-logs.md new file mode 100644 index 00000000000..8d482588cb1 --- /dev/null +++ b/docs/adr/facaccf3-6586-4106-b5ac-4ada57f5feb2-adopt-modelcontextprotocol-sdk-for-mcp-server-implementation-with-console-based-error-logging-tool-error-logs.md @@ -0,0 +1,114 @@ +# Adopt @modelcontextprotocol/sdk for MCP Server Implementation with Console-Based Error Logging: Tool Error Logs + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The android-device-mcp server implementation requires structured error reporting for tool execution failures and fatal errors +- The @modelcontextprotocol/sdk provides server infrastructure including server/index.js, server/stdio.js, and types.js modules for building MCP-compliant servers +- Console-based error logging is used for both tool-level errors (with tool name context) and fatal server errors +- The server operates in a real-time boundary context with tool discovery patterns using array find operations +- Error visibility is critical for debugging tool execution failures in the MCP server environment + +## Problem Statement + +MCP server implementations need consistent error logging that captures both tool-specific failures and fatal server errors while maintaining compatibility with the @modelcontextprotocol/sdk framework and stdio-based communication patterns. + +## Decision + +1. SHOULD: Tool error logs SHOULD include the tool name as context to facilitate debugging + +## Policy Block + +- SHOULD Tool error logs SHOULD include the tool name as context to facilitate debugging + +In scope: +- MCP server implementations using @modelcontextprotocol/sdk +- Tool execution error handling within MCP servers +- Fatal error reporting in server lifecycle +- stdio-based MCP server communication + +Out of scope: +- Client-side MCP implementations +- Structured logging frameworks (e.g., Winston, Bunyan) +- Application-level business logic logging +- Performance metrics or tracing + +## Rationale + +- The evidence shows consistent use of console.error for both tool-level and fatal errors, establishing a pattern for error visibility in MCP server contexts +- The @modelcontextprotocol/sdk provides the foundational server infrastructure, making it a core dependency for MCP server implementations +- Console-based logging aligns with stdio-based server communication patterns where structured logging frameworks might interfere with the protocol +- The pattern of including tool names in error messages provides essential context for debugging in a tool-discovery architecture + +## Consequences + +Positive: +- Simple, dependency-free error logging that works immediately without configuration +- Compatible with stdio-based MCP protocol communication without interference +- Clear error context through structured message formats including tool names +- Minimal overhead for error reporting in real-time server operations + +Negative: +- Console.error lacks structured logging capabilities (no log levels, filtering, or formatting) +- No built-in log aggregation or persistence mechanisms +- Limited observability compared to dedicated logging frameworks +- Difficult to implement log sampling or rate limiting for high-frequency errors + +## Alternatives + +- Use a structured logging framework like Winston or Pino (rejected) + Rejected because: Structured logging frameworks may interfere with stdio-based MCP protocol communication and add unnecessary dependencies for simple error reporting + When valid: When MCP servers require log aggregation, filtering, or integration with centralized logging systems +- Implement custom error handling without console output (rejected) + Rejected because: Silent error handling would eliminate visibility into tool failures and fatal errors, making debugging impossible + When valid: Never valid for server implementations requiring operational visibility +- Use process.stderr.write for direct stream writing (rejected) + Rejected because: Direct stream writing requires manual formatting and lacks the convenience of console.error while providing minimal benefit + When valid: When precise control over stderr buffering or formatting is required + +## Risks + +- Console.error output may interfere with MCP protocol messages on stdio if not properly separated + Mitigation: Ensure stderr is used for errors (console.error) while stdout is reserved for protocol messages + Owner: engineering team +- Lack of log levels makes it difficult to filter or prioritize errors in production + Mitigation: Use consistent message prefixes ('Tool error', 'Fatal error') to enable grep-based filtering + Owner: engineering team +- No log persistence means errors are lost if not captured by process supervisor + Mitigation: Deploy MCP servers with process managers that capture stderr (systemd, PM2, Docker logging) + Owner: operations team + +## Implementation Notes + +- Import Server and related types from @modelcontextprotocol/sdk/server/index.js and configure with name, version, and capabilities +- Wrap tool execution in try-catch blocks and log errors using console.error with the format 'Tool error ({toolName}): {error.message}' +- Implement top-level error handlers for fatal errors using console.error('Fatal error:', error) +- Ensure the server uses stdio transport from @modelcontextprotocol/sdk/server/stdio.js to maintain separation between protocol messages (stdout) and errors (stderr) + +## Continuation Context + + +Verify commands: +- grep -r "console\.error.*Tool error" .claude/mcp/android-device-server/src/ +- grep -r "console\.error.*Fatal error" .claude/mcp/android-device-server/src/ +- grep -r "@modelcontextprotocol/sdk" .claude/mcp/android-device-server/src/index.ts + +Accept when: +- All tool error logging uses console.error with 'Tool error ({name}):' prefix +- Fatal errors are logged with console.error using 'Fatal error:' prefix +- Server imports @modelcontextprotocol/sdk modules for server infrastructure + +## Enforcement + +- Verified by: Code review checking for console.error usage patterns +- Verified by: Grep-based verification commands in CI pipeline +- Verified by: Runtime testing of error scenarios to verify stderr output +- Violation handling: Code review feedback requesting correction to standard error logging format +- Violation handling: CI pipeline warnings for missing or non-standard error logging +- Violation handling: Documentation updates to clarify error logging requirements +- Exception process: Request exception through architecture review for alternative logging approaches +- Exception process: Document rationale for deviation including technical constraints +- Exception process: Obtain approval from platform team before implementing alternative logging \ No newline at end of file diff --git a/docs/adr/fc062a0d-97da-44ac-9afe-094108c24e86-standardize-collection-find-pattern-for-in-memory-data-queries-predicate-functions-passed.md b/docs/adr/fc062a0d-97da-44ac-9afe-094108c24e86-standardize-collection-find-pattern-for-in-memory-data-queries-predicate-functions-passed.md new file mode 100644 index 00000000000..fa1cc2450f2 --- /dev/null +++ b/docs/adr/fc062a0d-97da-44ac-9afe-094108c24e86-standardize-collection-find-pattern-for-in-memory-data-queries-predicate-functions-passed.md @@ -0,0 +1,100 @@ +# Standardize Collection.find() Pattern for In-Memory Data Queries: Predicate Functions Passed + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase demonstrates consistent use of JavaScript/TypeScript Array.find() method for querying in-memory collections across test specifications and automation scripts +- Test files in android-device-server use .find() with predicate functions to locate specific window objects by name property from parsed dumpsys output +- Python automation scripts use Set.add() operations for label and package name collection, indicating a pattern of in-memory data accumulation and membership testing +- The pattern appears in both testing contexts (vitest test suites) and operational contexts (GitHub automation scripts, JSON validation utilities) + +## Problem Statement + +Teams need a consistent, predictable approach for querying in-memory data structures to locate specific elements by property matching, particularly when working with parsed system output, configuration data, and test fixtures. Without standardization, different query patterns emerge that reduce code readability and increase cognitive load when navigating between modules. + +## Decision + +1. MUST: Predicate functions passed to .find() must test for property equality using strict comparison (===) or property name matching + +## Policy Block + +- MUST Predicate functions passed to .find() must test for property equality using strict comparison (===) or property name matching + +## Rationale + +- The pattern is observed across 3 files with 90.83% confidence, demonstrating consistent adoption in both test infrastructure and operational automation +- Array.find() provides clear semantic intent for single-element lookup operations, improving code readability compared to manual iteration +- Set.add() operations in Python scripts demonstrate parallel pattern of using language-native collection operations for membership and uniqueness constraints +- The pattern aligns with functional programming principles and modern JavaScript/TypeScript idioms, reducing imperative boilerplate + +## Consequences + +Positive: +- Improved code readability through consistent use of declarative collection query methods +- Reduced cognitive load when navigating between test specifications and automation scripts +- Better alignment with modern JavaScript/TypeScript idioms and functional programming patterns +- Clearer semantic intent in data access operations, making code review and maintenance easier + +Negative: +- Developers unfamiliar with functional array methods may require additional training or documentation +- Predicate function overhead may introduce minor performance cost compared to manual iteration in performance-critical paths +- Pattern may not extend cleanly to languages without first-class function support or equivalent collection APIs + +## Alternatives + +- Use manual for-loop iteration with conditional breaks for element lookup (rejected) + Rejected because: Manual iteration increases boilerplate code and reduces semantic clarity compared to declarative Array.find() method + When valid: Performance-critical paths where predicate function overhead is measured and significant +- Use Array.filter() followed by index access [0] for single-element lookup (rejected) + Rejected because: Array.filter() processes entire collection even after match is found, introducing unnecessary performance overhead + When valid: When subsequent operations require the filtered array or multiple matches are possible +- Use Map or Object lookup with key-based access instead of predicate-based search (deferred) + Rejected because: null + When valid: When data structure can be pre-indexed by lookup key and multiple queries justify indexing overhead + +## Risks + +- Performance degradation in large collections if .find() is used in tight loops or performance-critical paths + Mitigation: Profile data access patterns and consider pre-indexing with Map/Object for frequently queried large collections + Owner: engineering team +- Inconsistent adoption across polyglot codebase where Python, JavaScript, and TypeScript have different collection APIs + Mitigation: Document language-specific equivalents (Python: next(filter()), JavaScript/TypeScript: Array.find()) in coding standards + Owner: engineering team +- Undefined return values from .find() may cause runtime errors if not properly handled with null checks + Mitigation: Enforce TypeScript strict null checks and require explicit undefined handling in code review + Owner: engineering team + +## Implementation Notes + +- Use TypeScript strict mode to enforce null/undefined handling for .find() return values +- Consider creating utility functions for common query patterns (e.g., findByName, findById) to reduce predicate duplication +- Document the pattern in coding standards with examples from dumpsys.spec.ts showing window lookup by name property +- For Python code, use next(filter(predicate, collection), default) as the equivalent pattern to JavaScript Array.find() + +## Continuation Context + + +Verify commands: +- grep -r '\.find(.*=>.*===\|\w\+ => \w\+\.\w\+ ===' --include='*.ts' --include='*.js' . +- grep -r '\.add(' --include='*.py' . | grep -E '(labels|package_names|set)' +- npm test -- dumpsys.spec.ts 2>&1 | grep -E '(PASS|✓).*findOverlayAtPoint' + +Accept when: +- Grep commands identify at least 3 instances of Array.find() with predicate functions in TypeScript/JavaScript files +- Python scripts demonstrate Set.add() usage for collection building and membership operations +- Test suite for dumpsys parser passes with window lookup operations using .find() method + +## Enforcement + +- Verified by: Code review checklist includes verification of collection query patterns +- Verified by: ESLint rules configured to discourage manual iteration where Array methods are applicable +- Verified by: Test coverage requirements ensure query operations are tested with expected and missing elements +- Violation handling: Code review feedback requests refactoring of manual iteration to declarative collection methods +- Violation handling: ESLint warnings flagged in CI pipeline for review before merge +- Violation handling: Documentation links provided to developers during code review for pattern examples +- Exception process: Performance-critical paths may use manual iteration if profiling demonstrates measurable impact +- Exception process: Exception requests must include benchmark data comparing Array.find() vs manual iteration +- Exception process: Approved exceptions documented inline with comments explaining performance justification \ No newline at end of file diff --git a/docs/adr/ff882c06-6763-459c-a155-d6ee07394f95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-test-specifications-typescript.md b/docs/adr/ff882c06-6763-459c-a155-d6ee07394f95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-test-specifications-typescript.md new file mode 100644 index 00000000000..041e51af986 --- /dev/null +++ b/docs/adr/ff882c06-6763-459c-a155-d6ee07394f95-standardize-core-library-detection-and-data-access-patterns-in-test-and-automation-scripts-test-specifications-typescript.md @@ -0,0 +1,118 @@ +# Standardize Core Library Detection and Data Access Patterns in Test and Automation Scripts: Test Specifications Typescript + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Test specifications and automation scripts across the codebase demonstrate consistent patterns of importing core libraries (vitest, node:fs, node:path, argparse, json, sys, os) and performing data access operations using collection methods like find(), add(), and load(). +- The pattern emerges in three distinct contexts: TypeScript test files using vitest for parsing dumpsys output, Python scripts for GitHub PR labeling automation, and Python scripts for JSON validation, indicating a cross-language consistency in data access approaches. +- Data access patterns consistently involve in-memory collection operations (Set.add(), Array.find()) and file-based JSON loading (json.load(f)), suggesting a preference for simple, direct data manipulation over abstraction layers. +- The detection spans test frameworks (describe, it), standard library imports (node:fs, node:path, argparse, json, sys, os), and runtime libraries (vitest), indicating these are foundational dependencies for testing and automation workflows. + +## Problem Statement + +The codebase lacks explicit guidance on which core libraries and data access patterns should be used for test specifications and automation scripts, leading to potential inconsistency in how data is loaded, queried, and manipulated across different modules and languages. + +## Decision + +1. MUST: Test specifications in TypeScript MUST use vitest as the test framework with standard describe/it block structure for organizing test cases. + +## Policy Block + +- MUST Test specifications in TypeScript MUST use vitest as the test framework with standard describe/it block structure for organizing test cases. + +In scope: +- Test specification files (*.spec.ts, *.test.ts) +- Automation scripts in .github/scripts/ +- Validation and parsing utilities +- CI/CD pipeline scripts + +Out of scope: +- Production application code with complex query requirements +- Database access layers requiring ORM or query builders +- High-performance data processing pipelines +- Browser-based test runners (e.g., Playwright, Cypress) + +Exceptions: +- EXC-001: Performance profiling indicates native collection methods create bottlenecks in large dataset processing +- EXC-002: External API contracts require specific JSON schema validation libraries beyond standard json module capabilities + +## Rationale + +- The evidence shows consistent use of standard library modules across 3 files with 90.83% confidence, indicating an established pattern that minimizes external dependencies and reduces maintenance burden. +- Using native collection methods (find(), add()) and standard library JSON parsing provides predictable behavior, reduces bundle size, and eliminates version compatibility issues with third-party libraries. +- The pattern spans both TypeScript (vitest, node:fs, node:path) and Python (json, sys, os, argparse) contexts, demonstrating language-appropriate choices that align with ecosystem conventions. +- Direct data access patterns without abstraction layers are appropriate for the observed use cases (test parsing, label automation, JSON validation) where query complexity is low and transparency is valuable. + +## Consequences + +Positive: +- Reduced dependency footprint in test and automation scripts, minimizing security surface area and dependency update overhead +- Improved script portability and long-term maintainability by relying on stable standard library APIs rather than third-party package ecosystems +- Lower cognitive overhead for developers familiar with standard library APIs, reducing onboarding time for test and automation contributions +- Faster script execution and smaller bundle sizes due to elimination of unnecessary abstraction layers + +Negative: +- Limited query expressiveness for complex data access patterns, requiring manual predicate logic rather than declarative query syntax +- Potential code duplication if similar data access patterns are repeated across multiple scripts without shared utility functions +- Lack of type safety in Python json.load() operations without additional validation layers or schema enforcement +- Manual error handling required for file I/O and JSON parsing operations without framework-provided retry or validation mechanisms + +## Alternatives + +- Adopt lodash/underscore for collection operations and data manipulation in both TypeScript and Python scripts (rejected) + Rejected because: Evidence shows native methods (Array.find(), Set.add()) are sufficient for current use cases; adding lodash would increase bundle size and introduce unnecessary dependency without demonstrated performance or expressiveness benefits + When valid: Valid for scripts processing large datasets requiring complex transformations like groupBy, partition, or deep merging +- Use Pydantic or JSON Schema validators for structured JSON validation instead of raw json.load() (deferred) + Rejected because: Current validation scripts use simple duplicate detection and basic structure checks; schema validation libraries add complexity without clear evidence of validation requirements beyond basic parsing + When valid: Valid when external API contracts require strict schema enforcement or when validation error messages need to be user-facing +- Standardize on Jest instead of vitest for TypeScript test specifications (rejected) + Rejected because: Evidence explicitly shows vitest usage in test specifications; Jest would require migration effort and vitest provides faster execution with native ESM support + When valid: Valid for projects requiring Jest-specific ecosystem plugins or snapshot testing features not available in vitest + +## Risks + +- Scripts may grow complex enough that native collection methods become verbose and error-prone, leading to maintenance burden + Mitigation: Establish shared utility modules for common data access patterns; set complexity threshold (e.g., >3 nested loops) triggering refactor to query library + Owner: Engineering team +- Lack of schema validation in JSON loading may allow malformed data to propagate through automation pipelines, causing runtime failures + Mitigation: Add explicit validation checks after json.load() for critical fields; document expected JSON structure in script docstrings; consider schema validation for external data sources + Owner: DevOps and automation team +- Standard library file I/O patterns may not handle edge cases (encoding issues, large files, concurrent access) as robustly as specialized libraries + Mitigation: Document encoding assumptions (UTF-8) explicitly; add file size checks for large file handling; use file locking for concurrent access scenarios + Owner: Engineering team + +## Implementation Notes + +- Create shared utility modules for common patterns: parseJsonFile(), findInCollection(), addToSet() to reduce duplication while maintaining standard library usage +- Add ESLint/Pylint rules to flag imports of lodash, ramda, or other collection libraries in test and automation script directories +- Document standard library API patterns in developer guide with examples from existing scripts (dumpsys.spec.ts, label-pr.py, validate_json.py) +- For new automation scripts, use existing scripts as templates to ensure consistency in import patterns and data access approaches + +## Continuation Context + + +Verify commands: +- grep -r "import.*vitest" .claude/mcp/**/*.spec.ts | wc -l +- grep -r "import.*node:fs\|import.*node:path" .claude/mcp/**/*.ts .github/scripts/**/*.js | wc -l +- grep -r "import json\|import sys\|import os\|import argparse" .github/scripts/**/*.py | wc -l +- grep -r "\.find(\|.add(" .claude/mcp/**/*.spec.ts .github/scripts/**/*.py | wc -l + +Accept when: +- All TypeScript test specifications use vitest framework with describe/it structure and node:fs/node:path for file operations +- All Python automation scripts import only standard library modules (json, sys, os, argparse) for core functionality without external dependencies +- Data access patterns consistently use native collection methods (Array.find(), Set.add(), json.load()) across test and automation contexts + +## Enforcement + +- Verified by: CI pipeline static analysis checking for prohibited third-party imports in test and automation script directories +- Verified by: Code review checklist item verifying standard library usage for new test specifications and automation scripts +- Verified by: Automated dependency audits flagging new dependencies in package.json or requirements.txt within scope directories +- Violation handling: CI build fails if prohibited imports (lodash, ramda, etc.) are detected in test or automation scripts +- Violation handling: Pull requests adding external dependencies to automation scripts require architecture review and explicit justification +- Violation handling: Existing violations are tracked in technical debt backlog with migration plan to standard library equivalents +- Exception process: Submit exception request to tech lead with performance benchmarks or capability gap analysis +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration criteria +- Exception process: Review exceptions quarterly to assess if standard library improvements or refactoring can eliminate the need \ No newline at end of file