@synopackageland/cli 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/build-spk/generator.js +3 -0
- package/dist/build-spk/notices.d.ts +5 -0
- package/dist/build-spk/notices.js +60 -0
- package/dist/cli.js +9 -2
- package/dist/error-registry.js +20 -0
- package/dist/init.d.ts +4 -0
- package/dist/init.js +20 -12
- package/dist/standalone/build.js +3 -1
- package/dist/standalone/daemon.d.ts +23 -0
- package/dist/standalone/daemon.js +114 -0
- package/dist/standalone/dsm-window.d.ts +1 -1
- package/dist/standalone/dsm-window.js +50 -10
- package/dist/standalone/helper-inventory.d.ts +16 -0
- package/dist/standalone/helper-inventory.js +2 -0
- package/dist/standalone/helper.d.ts +2 -12
- package/dist/standalone/helper.js +8 -7
- package/dist/standalone/host-adapter.d.ts +5 -0
- package/dist/standalone/host-adapter.js +148 -0
- package/dist/standalone/host-platform.d.ts +13 -0
- package/dist/standalone/host-platform.js +42 -0
- package/dist/standalone/host-types.d.ts +49 -0
- package/dist/standalone/host-types.js +1 -0
- package/dist/standalone/inspect-helper.d.ts +6 -0
- package/dist/standalone/inspect-helper.js +88 -0
- package/dist/standalone/inspect-spk.d.ts +2 -0
- package/dist/standalone/inspect-spk.js +49 -0
- package/dist/standalone/lifecycle-helper.d.ts +2 -0
- package/dist/standalone/lifecycle-helper.js +12 -0
- package/dist/standalone/lifecycle.d.ts +3 -0
- package/dist/standalone/lifecycle.js +53 -0
- package/dist/standalone/manifest.d.ts +2 -0
- package/dist/standalone/manifest.js +4 -1
- package/dist/standalone/reopen-events.d.ts +2 -0
- package/dist/standalone/reopen-events.js +28 -0
- package/dist/standalone/root-messages.js +9 -0
- package/dist/standalone/root-window.d.ts +4 -3
- package/dist/standalone/root-window.js +17 -5
- package/dist/standalone/spk.d.ts +4 -3
- package/dist/standalone/spk.js +20 -33
- package/dist/template-paths.d.ts +2 -0
- package/dist/template-paths.js +9 -0
- package/dist/templates/_daemon/fixture_linux_test.go +15 -0
- package/dist/templates/_daemon/fixture_other_test.go +7 -0
- package/dist/templates/_daemon/go.mod +3 -0
- package/dist/templates/_daemon/main.go +608 -0
- package/dist/templates/_daemon/main_test.go +242 -0
- package/dist/templates/_daemon/process_linux.go +55 -0
- package/dist/templates/_daemon/process_linux_test.go +161 -0
- package/dist/templates/_daemon/process_other.go +14 -0
- package/dist/templates/_daemon/testdata/child.go +41 -0
- package/dist/templates/_shared/GO-LICENSE +27 -0
- package/dist/templates/_shared/GO-PATENTS +22 -0
- package/dist/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/dist/templates/_shared/notice-overrides/index.json +14 -0
- package/dist/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/dist/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/dist/templates/_shared/third-party-notices.mjs +51 -0
- package/dist/templates/native-go/README.md +57 -1
- package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/dist/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/dist/templates/native-go/backend/go.mod +4 -0
- package/dist/templates/native-go/backend/go.sum +4 -0
- package/dist/templates/native-go/backend/internal/api/binary.go +154 -0
- package/dist/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/dist/templates/native-go/backend/internal/api/registry.go +14 -4
- package/dist/templates/native-go/backend/internal/api/server.go +4 -0
- package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/dist/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +11 -0
- package/dist/templates/native-go/backend/internal/app/routes_test.go +10 -5
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/dist/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/control.go +226 -21
- package/dist/templates/native-go/backend/internal/helper/control_test.go +10 -2
- package/dist/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/dist/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/dist/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/dist/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/dist/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/dist/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/dist/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/dist/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/dist/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/dist/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/dist/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/dist/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/dist/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/dist/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/dist/templates/native-go/backend/internal/helper/process_linux.go +11 -1
- package/dist/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/dist/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/dist/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/dist/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/server_linux.go +44 -3
- package/dist/templates/native-go/backend/internal/helper/status.go +74 -11
- package/dist/templates/native-go/backend/internal/helper/status_test.go +83 -0
- package/dist/templates/native-go/backend/internal/helper/supervision.go +28 -5
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +187 -16
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux_test.go +618 -7
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/dist/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/dist/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/dist/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/dist/templates/native-go/backend/internal/helper/write.go +77 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/dist/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/dist/templates/native-go/ui/app.js +8 -1
- package/dist/templates/native-go-better-auth/node/build.mjs +2 -0
- package/dist/templates/native-go-vue/README.md +115 -1
- package/dist/templates/native-go-vue/frontend/DESIGN.md +1 -1
- package/dist/templates/native-go-vue/frontend/package-lock.json +132 -229
- package/dist/templates/native-go-vue/frontend/package.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/App.vue +33 -6
- package/dist/templates/native-go-vue/frontend/src/context.ts +41 -2
- package/dist/templates/native-go-vue/frontend/src/main.ts +4 -1
- package/dist/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/dist/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/dist/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/dist/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/dist/templates/native-go-vue/frontend/src/style.css +17 -0
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +44 -2
- package/dist/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/dist/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/dist/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/dist/templates/native-go-vue/frontend/tsconfig.json +1 -1
- package/dist/templates/native-go-vue/frontend/vite.config.ts +6 -4
- package/package.json +3 -2
- package/templates/_daemon/fixture_linux_test.go +15 -0
- package/templates/_daemon/fixture_other_test.go +7 -0
- package/templates/_daemon/go.mod +3 -0
- package/templates/_daemon/main.go +608 -0
- package/templates/_daemon/main_test.go +242 -0
- package/templates/_daemon/process_linux.go +55 -0
- package/templates/_daemon/process_linux_test.go +161 -0
- package/templates/_daemon/process_other.go +14 -0
- package/templates/_daemon/testdata/child.go +41 -0
- package/templates/_shared/GO-LICENSE +27 -0
- package/templates/_shared/GO-PATENTS +22 -0
- package/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/templates/_shared/notice-overrides/index.json +14 -0
- package/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/templates/_shared/third-party-notices.mjs +51 -0
- package/templates/native-go/README.md +57 -1
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/templates/native-go/backend/go.mod +4 -0
- package/templates/native-go/backend/go.sum +4 -0
- package/templates/native-go/backend/internal/api/binary.go +154 -0
- package/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/templates/native-go/backend/internal/api/registry.go +14 -4
- package/templates/native-go/backend/internal/api/server.go +4 -0
- package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/templates/native-go/backend/internal/app/routes.go +11 -0
- package/templates/native-go/backend/internal/app/routes_test.go +10 -5
- package/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/templates/native-go/backend/internal/helper/control.go +226 -21
- package/templates/native-go/backend/internal/helper/control_test.go +10 -2
- package/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/templates/native-go/backend/internal/helper/process_linux.go +11 -1
- package/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/templates/native-go/backend/internal/helper/server_linux.go +44 -3
- package/templates/native-go/backend/internal/helper/status.go +74 -11
- package/templates/native-go/backend/internal/helper/status_test.go +83 -0
- package/templates/native-go/backend/internal/helper/supervision.go +28 -5
- package/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux.go +187 -16
- package/templates/native-go/backend/internal/helper/supervisor_linux_test.go +618 -7
- package/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/templates/native-go/backend/internal/helper/write.go +77 -0
- package/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/templates/native-go/ui/app.js +8 -1
- package/templates/native-go-better-auth/node/build.mjs +2 -0
- package/templates/native-go-vue/README.md +115 -1
- package/templates/native-go-vue/frontend/DESIGN.md +1 -1
- package/templates/native-go-vue/frontend/package-lock.json +132 -229
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-go-vue/frontend/src/App.vue +33 -6
- package/templates/native-go-vue/frontend/src/context.ts +41 -2
- package/templates/native-go-vue/frontend/src/main.ts +4 -1
- package/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/templates/native-go-vue/frontend/src/style.css +17 -0
- package/templates/native-go-vue/frontend/test/apps.test.ts +44 -2
- package/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/templates/native-go-vue/frontend/tsconfig.json +1 -1
- package/templates/native-go-vue/frontend/vite.config.ts +6 -4
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"golang.org/x/sys/unix"
|
|
6
|
+
"runtime"
|
|
7
|
+
"strconv"
|
|
8
|
+
"syscall"
|
|
9
|
+
"time"
|
|
10
|
+
"unsafe"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
// Private trusted certification input; no environment/JSON/RPC can assert it.
|
|
14
|
+
// Source layout alone is insufficient: actual target/build/masks must be proven.
|
|
15
|
+
type dsmACLRuntimeProof struct {
|
|
16
|
+
Architecture, BuildRef, BootRef string
|
|
17
|
+
LayoutVerified, MasksVerified bool
|
|
18
|
+
CheckedAt time.Time
|
|
19
|
+
}
|
|
20
|
+
type dsmACLSyscallBridge struct {
|
|
21
|
+
proof func(context.Context) (dsmACLRuntimeProof, Code)
|
|
22
|
+
now func() time.Time
|
|
23
|
+
call func(uintptr, uintptr, uintptr, uintptr) (uintptr, syscall.Errno)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func newDSMACLSyscallBridge(p func(context.Context) (dsmACLRuntimeProof, Code)) *dsmACLSyscallBridge {
|
|
27
|
+
return &dsmACLSyscallBridge{proof: p, now: time.Now, call: func(n, a, b, c uintptr) (uintptr, syscall.Errno) { r, _, e := syscall.Syscall(n, a, b, c); return r, e }}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Source layout: DSM7-4 linux-4.4.x 29003c4, generic + x86-64 table.
|
|
31
|
+
// The same numbers do not imply support on ordinary Linux or another DSM build.
|
|
32
|
+
const dsmACLCheckSyscall = 812
|
|
33
|
+
const dsmACLSupportSyscall = 813
|
|
34
|
+
|
|
35
|
+
func (b *dsmACLSyscallBridge) Check(ctx context.Context, fd int, alias string, mask uint32) (nativeFDACLObservation, Code) {
|
|
36
|
+
empty := nativeFDACLObservation{}
|
|
37
|
+
if b == nil || b.proof == nil || b.call == nil || b.now == nil {
|
|
38
|
+
return empty, ErrUnsupported
|
|
39
|
+
}
|
|
40
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
41
|
+
return empty, c
|
|
42
|
+
}
|
|
43
|
+
p, c := b.proof(ctx)
|
|
44
|
+
if c = nativeObservationCode(ctx, c); c != "" {
|
|
45
|
+
return empty, c
|
|
46
|
+
}
|
|
47
|
+
if (runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64") || p.Architecture != runtime.GOARCH || !p.LayoutVerified || !p.MasksVerified || !allReferences(p.BuildRef, p.BootRef) || !nativeFresh(p.CheckedAt, b.now()) {
|
|
48
|
+
return empty, ErrUnsupported
|
|
49
|
+
}
|
|
50
|
+
if fd < 0 || alias != "/proc/self/fd/"+strconv.Itoa(fd) || mask == 0 || mask & ^(nativeACLExec|nativeACLRead|nativeACLReadAttr) != 0 {
|
|
51
|
+
return empty, ErrInvalid
|
|
52
|
+
}
|
|
53
|
+
errorCode := func(e syscall.Errno) Code {
|
|
54
|
+
if e == unix.ENOSYS || e == unix.EOPNOTSUPP {
|
|
55
|
+
return ErrUnsupported
|
|
56
|
+
}
|
|
57
|
+
return ErrUnavailable
|
|
58
|
+
}
|
|
59
|
+
name, err := unix.BytePtrFromString(alias)
|
|
60
|
+
if err != nil {
|
|
61
|
+
return empty, ErrInvalid
|
|
62
|
+
}
|
|
63
|
+
defer runtime.KeepAlive(name)
|
|
64
|
+
// Positive FD support is mandatory. With WINACL compiled out this returns 0,
|
|
65
|
+
// which MUST refuse before the check syscall's misleading zero-success stub.
|
|
66
|
+
// Kernel fget excludes O_PATH: resolve the SAME fixed alias for support too.
|
|
67
|
+
// No original pathname, readable reopen, or POSIX fallback is introduced.
|
|
68
|
+
for _, tag := range []uintptr{1, 2} {
|
|
69
|
+
supported, e := b.call(dsmACLSupportSyscall, uintptr(unsafe.Pointer(name)), uintptr(fd), tag)
|
|
70
|
+
if e != 0 {
|
|
71
|
+
return empty, errorCode(e)
|
|
72
|
+
}
|
|
73
|
+
if supported != 1 {
|
|
74
|
+
return empty, ErrUnsupported
|
|
75
|
+
}
|
|
76
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
77
|
+
return empty, c
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
result, e := b.call(dsmACLCheckSyscall, uintptr(unsafe.Pointer(name)), uintptr(mask), 0)
|
|
81
|
+
runtime.KeepAlive(name)
|
|
82
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
83
|
+
return empty, c
|
|
84
|
+
}
|
|
85
|
+
if e != 0 && e != unix.EACCES && e != unix.EPERM {
|
|
86
|
+
return empty, errorCode(e)
|
|
87
|
+
}
|
|
88
|
+
if e == 0 && result != 0 {
|
|
89
|
+
return empty, ErrUnavailable
|
|
90
|
+
}
|
|
91
|
+
if !nativeFresh(p.CheckedAt, b.now()) {
|
|
92
|
+
return empty, ErrStale
|
|
93
|
+
}
|
|
94
|
+
return nativeFDACLObservation{FilesystemSupported: true, ObjectSupported: true, MasksVerified: true, Allowed: e == 0, CheckedAt: p.CheckedAt}, ""
|
|
95
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"runtime"
|
|
6
|
+
"syscall"
|
|
7
|
+
"testing"
|
|
8
|
+
"time"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
func TestDSMNativeSyscallsRequirePositiveProofAndSupport(t *testing.T) {
|
|
12
|
+
now := time.Now()
|
|
13
|
+
calls := 0
|
|
14
|
+
b := newDSMACLSyscallBridge(func(context.Context) (dsmACLRuntimeProof, Code) { return dsmACLRuntimeProof{}, "" })
|
|
15
|
+
b.call = func(uintptr, uintptr, uintptr, uintptr) (uintptr, syscall.Errno) { calls++; return 0, 0 }
|
|
16
|
+
if _, c := b.Check(context.Background(), 5, "/proc/self/fd/5", nativeACLRead); c != ErrUnsupported || calls != 0 {
|
|
17
|
+
t.Fatal("unknown target invoked custom syscall", c, calls)
|
|
18
|
+
}
|
|
19
|
+
b.proof = func(context.Context) (dsmACLRuntimeProof, Code) {
|
|
20
|
+
return dsmACLRuntimeProof{Architecture: runtime.GOARCH, BuildRef: grantRef('a'), BootRef: grantRef('b'), LayoutVerified: true, MasksVerified: true, CheckedAt: now}, ""
|
|
21
|
+
}
|
|
22
|
+
b.now = func() time.Time { return now }
|
|
23
|
+
if _, c := b.Check(context.Background(), 5, "/proc/self/fd/5", nativeACLRead); c != ErrUnsupported || calls != 1 {
|
|
24
|
+
t.Fatal("no-WINACL zero treated as Allow", c, calls)
|
|
25
|
+
}
|
|
26
|
+
b.call = func(n, a1, a2, a3 uintptr) (uintptr, syscall.Errno) {
|
|
27
|
+
calls++
|
|
28
|
+
if n == 813 {
|
|
29
|
+
if a1 == 0 || (a3 != 1 && a3 != 2) {
|
|
30
|
+
t.Fatal("O_PATH support must resolve the pinned alias, not fget")
|
|
31
|
+
}
|
|
32
|
+
return 1, 0
|
|
33
|
+
}
|
|
34
|
+
if n != 812 {
|
|
35
|
+
t.Fatal(n)
|
|
36
|
+
}
|
|
37
|
+
return 0, 0
|
|
38
|
+
}
|
|
39
|
+
o, c := b.Check(context.Background(), 5, "/proc/self/fd/5", nativeACLRead|nativeACLReadAttr)
|
|
40
|
+
if c != "" || !o.Allowed || !o.ObjectSupported {
|
|
41
|
+
t.Fatal(c, o)
|
|
42
|
+
}
|
|
43
|
+
if _, c = b.Check(context.Background(), 5, "/proc/self/fd/6", nativeACLRead); c == "" {
|
|
44
|
+
t.Fatal("alias substitution")
|
|
45
|
+
}
|
|
46
|
+
b.call = func(n, a1, a2, a3 uintptr) (uintptr, syscall.Errno) {
|
|
47
|
+
if n == 813 {
|
|
48
|
+
return 1, 0
|
|
49
|
+
}
|
|
50
|
+
return 0, syscall.EACCES
|
|
51
|
+
}
|
|
52
|
+
o, c = b.Check(context.Background(), 5, "/proc/self/fd/5", nativeACLRead)
|
|
53
|
+
if c != "" || o.Allowed {
|
|
54
|
+
t.Fatal("native deny", c, o)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"dsmapp/internal/dsmprobe"
|
|
6
|
+
"runtime"
|
|
7
|
+
"slices"
|
|
8
|
+
"time"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// Certificates are private root-side audit input, never probe/browser flags.
|
|
12
|
+
// No certificate or bridge is installed in shipped supervisor adapters.
|
|
13
|
+
type dsmBridgeCertificate struct {
|
|
14
|
+
Architecture, DSMBuild, Kernel, Fingerprint, BootRef string
|
|
15
|
+
NativeGettersAudited, LayoutAudited, MasksAudited bool
|
|
16
|
+
}
|
|
17
|
+
type dsmProbeTransport interface {
|
|
18
|
+
Observe(context.Context, dsmprobe.Request) (dsmprobe.Response, Code)
|
|
19
|
+
}
|
|
20
|
+
type dsmNativeBridge struct {
|
|
21
|
+
transport dsmProbeTransport
|
|
22
|
+
certificate *dsmBridgeCertificate
|
|
23
|
+
now func() time.Time
|
|
24
|
+
}
|
|
25
|
+
type dsmShareObservation struct {
|
|
26
|
+
Principal Principal
|
|
27
|
+
SessionRef, Name, Path string
|
|
28
|
+
Available, VolumeProven, ReadAllowed bool
|
|
29
|
+
CheckedAt time.Time
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func newDSMNativeBridge(t dsmProbeTransport, c *dsmBridgeCertificate) *dsmNativeBridge {
|
|
33
|
+
b := &dsmNativeBridge{transport: t, now: time.Now}
|
|
34
|
+
if c != nil {
|
|
35
|
+
copy := *c
|
|
36
|
+
b.certificate = ©
|
|
37
|
+
}
|
|
38
|
+
return b
|
|
39
|
+
}
|
|
40
|
+
func (b *dsmNativeBridge) observe(ctx context.Context, actor *NativeActor) (dsmprobe.Response, time.Time, Code) {
|
|
41
|
+
var zero dsmprobe.Response
|
|
42
|
+
if b == nil || b.transport == nil || b.certificate == nil || b.now == nil {
|
|
43
|
+
return zero, time.Time{}, ErrUnsupported
|
|
44
|
+
}
|
|
45
|
+
cert := *b.certificate
|
|
46
|
+
if !allReferences(cert.Fingerprint, cert.BootRef) || cert.Architecture == "" || cert.DSMBuild == "" || cert.Kernel == "" {
|
|
47
|
+
return zero, time.Time{}, ErrUnsupported
|
|
48
|
+
}
|
|
49
|
+
started := b.now()
|
|
50
|
+
ctx, cancel := context.WithTimeout(ctx, NativeProofFreshness)
|
|
51
|
+
defer cancel()
|
|
52
|
+
nonce, c := randomGrantID()
|
|
53
|
+
if c != "" {
|
|
54
|
+
return zero, started, c
|
|
55
|
+
}
|
|
56
|
+
request := dsmprobe.Request{Version: dsmprobe.Protocol, Nonce: nonce, Kind: "runtime", Groups: []uint32{}}
|
|
57
|
+
if actor != nil {
|
|
58
|
+
if !actor.valid || actor.Principal().Kind != "local" || !actor.account.Enabled || !nativeFresh(actor.account.CheckedAt, started) {
|
|
59
|
+
return zero, started, ErrDenied
|
|
60
|
+
}
|
|
61
|
+
request.Kind = "metadata"
|
|
62
|
+
request.Username = actor.Username()
|
|
63
|
+
request.UID = actor.UID()
|
|
64
|
+
request.GID = actor.GID()
|
|
65
|
+
request.Groups = actor.Groups()
|
|
66
|
+
}
|
|
67
|
+
out, c := b.transport.Observe(ctx, request)
|
|
68
|
+
if c = nativeObservationCode(ctx, c); c != "" {
|
|
69
|
+
return zero, started, c
|
|
70
|
+
}
|
|
71
|
+
if !nativeFresh(started, b.now()) {
|
|
72
|
+
return zero, started, ErrStale
|
|
73
|
+
}
|
|
74
|
+
if out.Version != dsmprobe.Protocol || out.Nonce != nonce || out.Status != "ok" || out.Runtime.Architecture != cert.Architecture || out.Runtime.DSMBuild != cert.DSMBuild || out.Runtime.Kernel != cert.Kernel || out.Runtime.Fingerprint != cert.Fingerprint || out.Runtime.BootRef != cert.BootRef {
|
|
75
|
+
return zero, started, ErrUnsupported
|
|
76
|
+
}
|
|
77
|
+
if actor != nil {
|
|
78
|
+
a := out.Account
|
|
79
|
+
identity := out.Identity
|
|
80
|
+
if !cert.NativeGettersAudited || !a.NativeKnown || !a.Local || !a.Enabled || !a.GroupsKnown || a.Username != actor.Username() || a.UID != actor.UID() || a.GID != actor.GID() || !slices.Equal(a.Groups, actor.Groups()) || identity.UID != actor.UID() || identity.GID != actor.GID() || !slices.Equal(identity.Groups, actor.Groups()) || !identity.NoNewPrivs || !identity.NonDumpable {
|
|
81
|
+
return zero, started, ErrDenied
|
|
82
|
+
}
|
|
83
|
+
if !nativeFresh(actor.account.CheckedAt, b.now()) {
|
|
84
|
+
return zero, started, ErrStale
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out, started, ""
|
|
88
|
+
}
|
|
89
|
+
func nativeShareFacts(s dsmprobe.Share) Code {
|
|
90
|
+
if !s.NativeKnown || !s.VolumeKnown || !s.PermissionKnown {
|
|
91
|
+
return ErrUnsupported
|
|
92
|
+
}
|
|
93
|
+
if !s.Available || !s.ReadAllowed {
|
|
94
|
+
return ErrDenied
|
|
95
|
+
}
|
|
96
|
+
if ValidateRelativeSegments([]string{s.Name}, false) != "" {
|
|
97
|
+
return ErrInvalid
|
|
98
|
+
}
|
|
99
|
+
return (readOnlyWork{RootPath: s.Path, Action: ActionStat, Segments: []string{}}).validate()
|
|
100
|
+
}
|
|
101
|
+
func (b *dsmNativeBridge) ObserveOwnHome(ctx context.Context, a NativeActor) (ownHomeObservation, Code) {
|
|
102
|
+
out, at, c := b.observe(ctx, &a)
|
|
103
|
+
if c != "" {
|
|
104
|
+
return ownHomeObservation{}, c
|
|
105
|
+
}
|
|
106
|
+
if c = nativeShareFacts(out.Share); c != "" {
|
|
107
|
+
return ownHomeObservation{}, c
|
|
108
|
+
}
|
|
109
|
+
if !out.Home.StatusKnown {
|
|
110
|
+
return ownHomeObservation{}, ErrUnsupported
|
|
111
|
+
}
|
|
112
|
+
if !out.Home.Enabled || out.Share.Name != "homes" || out.Share.Path != out.Home.HomesPath || out.Account.Home != "/var/services/homes/"+a.Username() {
|
|
113
|
+
return ownHomeObservation{}, ErrDenied
|
|
114
|
+
}
|
|
115
|
+
return ownHomeObservation{Principal: a.Principal(), SessionRef: a.SessionRef(), Home: out.Account.Home, HomesPath: out.Home.HomesPath, Enabled: true, ShareAllowed: true, VolumeProven: true, CheckedAt: at}, ""
|
|
116
|
+
}
|
|
117
|
+
func (b *dsmNativeBridge) ObserveShare(ctx context.Context, a NativeActor, name string) (dsmShareObservation, Code) {
|
|
118
|
+
if name != "homes" {
|
|
119
|
+
return dsmShareObservation{}, ErrUnsupported
|
|
120
|
+
} // This slice certifies only the own-home native homes share.
|
|
121
|
+
out, at, c := b.observe(ctx, &a)
|
|
122
|
+
if c != "" {
|
|
123
|
+
return dsmShareObservation{}, c
|
|
124
|
+
}
|
|
125
|
+
if out.Share.Name != name {
|
|
126
|
+
return dsmShareObservation{}, ErrStale
|
|
127
|
+
}
|
|
128
|
+
if c = nativeShareFacts(out.Share); c != "" {
|
|
129
|
+
return dsmShareObservation{}, c
|
|
130
|
+
}
|
|
131
|
+
return dsmShareObservation{Principal: a.Principal(), SessionRef: a.SessionRef(), Name: name, Path: out.Share.Path, Available: true, VolumeProven: true, ReadAllowed: true, CheckedAt: at}, ""
|
|
132
|
+
}
|
|
133
|
+
func (b *dsmNativeBridge) ACLRuntimeProof(ctx context.Context) (dsmACLRuntimeProof, Code) {
|
|
134
|
+
out, at, c := b.observe(ctx, nil)
|
|
135
|
+
if c != "" {
|
|
136
|
+
return dsmACLRuntimeProof{}, c
|
|
137
|
+
}
|
|
138
|
+
cert := *b.certificate
|
|
139
|
+
if cert.Architecture != runtime.GOARCH || (runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64") || !cert.LayoutAudited || !cert.MasksAudited {
|
|
140
|
+
return dsmACLRuntimeProof{}, ErrUnsupported
|
|
141
|
+
}
|
|
142
|
+
// An ACL sample's result/certified flag is never native action certification.
|
|
143
|
+
return dsmACLRuntimeProof{Architecture: out.Runtime.Architecture, BuildRef: cert.Fingerprint, BootRef: cert.BootRef, LayoutVerified: true, MasksVerified: true, CheckedAt: at}, ""
|
|
144
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"dsmapp/internal/dsmprobe"
|
|
6
|
+
"runtime"
|
|
7
|
+
"testing"
|
|
8
|
+
"time"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
type nativeProbeFake struct {
|
|
12
|
+
response dsmprobe.Response
|
|
13
|
+
code Code
|
|
14
|
+
change func(*dsmprobe.Response)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func (f *nativeProbeFake) Observe(_ context.Context, r dsmprobe.Request) (dsmprobe.Response, Code) {
|
|
18
|
+
v := f.response
|
|
19
|
+
v.Nonce = r.Nonce
|
|
20
|
+
v.Version = 1
|
|
21
|
+
if f.change != nil {
|
|
22
|
+
f.change(&v)
|
|
23
|
+
}
|
|
24
|
+
return v, f.code
|
|
25
|
+
}
|
|
26
|
+
func bridgeFixture(t *testing.T) (*dsmNativeBridge, NativeActor, *nativeProbeFake) {
|
|
27
|
+
t.Helper()
|
|
28
|
+
p, _, _, carriers, now := nativeFixture()
|
|
29
|
+
actor, c := p.Resolve(context.Background(), carriers)
|
|
30
|
+
if c != "" {
|
|
31
|
+
t.Fatal(c)
|
|
32
|
+
}
|
|
33
|
+
actor.account.Username = "normal3"
|
|
34
|
+
f := &nativeProbeFake{response: dsmprobe.Response{Version: 1, Status: "ok", Runtime: dsmprobe.Runtime{Architecture: runtime.GOARCH, DSMBuild: "7.4-90069", Kernel: "4.4.302+", BootRef: grantRef('b'), Fingerprint: grantRef('f')}, Identity: dsmprobe.Identity{UID: actor.UID(), GID: actor.GID(), Groups: actor.Groups(), NoNewPrivs: true, NonDumpable: true}, Account: dsmprobe.Account{Username: actor.Username(), UID: actor.UID(), GID: actor.GID(), Groups: actor.Groups(), Home: "/var/services/homes/normal3", NativeKnown: true, Local: true, Enabled: true, GroupsKnown: true}, Home: dsmprobe.Home{HomesPath: "/volume1/homes", StatusKnown: true, Enabled: true}, Share: dsmprobe.Share{Name: "homes", Path: "/volume1/homes", NativeKnown: true, Available: true, VolumeKnown: true, PermissionKnown: true, ReadAllowed: true}}}
|
|
35
|
+
cert := &dsmBridgeCertificate{Architecture: runtime.GOARCH, DSMBuild: "7.4-90069", Kernel: "4.4.302+", Fingerprint: grantRef('f'), BootRef: grantRef('b'), NativeGettersAudited: true, LayoutAudited: true, MasksAudited: true}
|
|
36
|
+
b := &dsmNativeBridge{transport: f, certificate: cert, now: func() time.Time { return now }}
|
|
37
|
+
return b, actor, f
|
|
38
|
+
}
|
|
39
|
+
func TestDSMNativeBridgeRequiresIndependentNativeFacts(t *testing.T) {
|
|
40
|
+
b, a, f := bridgeFixture(t)
|
|
41
|
+
o, c := b.ObserveOwnHome(context.Background(), a)
|
|
42
|
+
if c != "" || o.Home != "/var/services/homes/normal3" || !o.ShareAllowed {
|
|
43
|
+
t.Fatal(c, o)
|
|
44
|
+
}
|
|
45
|
+
for _, change := range []func(*dsmprobe.Response){func(r *dsmprobe.Response) { r.Share.PermissionKnown = false }, func(r *dsmprobe.Response) { r.Account.GroupsKnown = false }, func(r *dsmprobe.Response) { r.Home.StatusKnown = false }, func(r *dsmprobe.Response) { r.Share.VolumeKnown = false }, func(r *dsmprobe.Response) { r.Account.UID++ }, func(r *dsmprobe.Response) { r.Runtime.Fingerprint = grantRef('e') }, func(r *dsmprobe.Response) { r.Identity.NoNewPrivs = false }} {
|
|
46
|
+
f.change = change
|
|
47
|
+
if _, c := b.ObserveOwnHome(context.Background(), a); c == "" {
|
|
48
|
+
t.Fatal("unknown proof accepted")
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
f.change = nil
|
|
52
|
+
b.certificate = nil
|
|
53
|
+
if _, c := b.ObserveOwnHome(context.Background(), a); c == "" {
|
|
54
|
+
t.Fatal("no audit certificate accepted")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
func TestDSMNativeBridgeACLProofNeverUsesProbeAllowFlag(t *testing.T) {
|
|
58
|
+
b, _, f := bridgeFixture(t)
|
|
59
|
+
p, c := b.ACLRuntimeProof(context.Background())
|
|
60
|
+
if c != "" || !p.LayoutVerified || !p.MasksVerified {
|
|
61
|
+
t.Fatal(c, p)
|
|
62
|
+
}
|
|
63
|
+
f.response.ACL.Certified = true
|
|
64
|
+
f.response.ACL.CheckResult = 0
|
|
65
|
+
b.certificate.MasksAudited = false
|
|
66
|
+
if _, c = b.ACLRuntimeProof(context.Background()); c == "" {
|
|
67
|
+
t.Fatal("unknown masks accepted")
|
|
68
|
+
}
|
|
69
|
+
b.certificate.MasksAudited = true
|
|
70
|
+
f.change = func(r *dsmprobe.Response) { r.Runtime.BootRef = grantRef('d') }
|
|
71
|
+
if _, c = b.ACLRuntimeProof(context.Background()); c == "" {
|
|
72
|
+
t.Fatal("different boot accepted")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
func TestDSMNativeShareBridgeIsOwnHomesOnlyAndProofBound(t *testing.T) {
|
|
77
|
+
b, a, f := bridgeFixture(t)
|
|
78
|
+
o, c := b.ObserveShare(context.Background(), a, "homes")
|
|
79
|
+
if c != "" || o.Path != "/volume1/homes" || o.Principal != a.Principal() || o.SessionRef != a.SessionRef() {
|
|
80
|
+
t.Fatal(c, o)
|
|
81
|
+
}
|
|
82
|
+
if _, c = b.ObserveShare(context.Background(), a, "public"); c != ErrUnsupported {
|
|
83
|
+
t.Fatal("unreviewed share", c)
|
|
84
|
+
}
|
|
85
|
+
f.change = func(r *dsmprobe.Response) { r.Share.ReadAllowed = false }
|
|
86
|
+
if _, c = b.ObserveShare(context.Background(), a, "homes"); c != ErrDenied {
|
|
87
|
+
t.Fatal(c)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"golang.org/x/sys/unix"
|
|
6
|
+
"strings"
|
|
7
|
+
"time"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// This read-only observation must use fresh local pw_dir + home status + native
|
|
11
|
+
// homes mapping; never HomePathGet/prepare-folder, NSS, or guessed volume paths.
|
|
12
|
+
type ownHomeObservation struct {
|
|
13
|
+
Principal Principal
|
|
14
|
+
SessionRef, Home, HomesPath string
|
|
15
|
+
Enabled, ShareAllowed, VolumeProven bool
|
|
16
|
+
CheckedAt time.Time
|
|
17
|
+
}
|
|
18
|
+
type ownHomeBridge interface {
|
|
19
|
+
ObserveOwnHome(context.Context, NativeActor) (ownHomeObservation, Code)
|
|
20
|
+
}
|
|
21
|
+
type dsmOwnHomeResolver struct {
|
|
22
|
+
native ownHomeBridge
|
|
23
|
+
now func() time.Time
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func (r *dsmOwnHomeResolver) Resolve(ctx context.Context, actor NativeActor) (*pinnedReadOnlyRoot, Code) {
|
|
27
|
+
if r == nil || r.native == nil || r.now == nil {
|
|
28
|
+
return nil, ErrUnavailable
|
|
29
|
+
}
|
|
30
|
+
if !actor.valid || !nativeFresh(actor.account.CheckedAt, r.now()) {
|
|
31
|
+
return nil, ErrDenied
|
|
32
|
+
}
|
|
33
|
+
ctx, cancel := context.WithTimeout(ctx, MetadataTimeout)
|
|
34
|
+
defer cancel()
|
|
35
|
+
before, c := r.native.ObserveOwnHome(ctx, actor)
|
|
36
|
+
if c = nativeObservationCode(ctx, c); c != "" {
|
|
37
|
+
return nil, c
|
|
38
|
+
}
|
|
39
|
+
validate := func(o ownHomeObservation) Code {
|
|
40
|
+
if o.Principal != actor.Principal() || o.SessionRef != actor.SessionRef() || !o.Enabled || !o.ShareAllowed {
|
|
41
|
+
return ErrDenied
|
|
42
|
+
}
|
|
43
|
+
if !o.VolumeProven {
|
|
44
|
+
return ErrUnsupported
|
|
45
|
+
}
|
|
46
|
+
if !nativeFresh(o.CheckedAt, r.now()) || !nativeFresh(actor.account.CheckedAt, r.now()) {
|
|
47
|
+
return ErrStale
|
|
48
|
+
}
|
|
49
|
+
// Only the fixed native alias is recognized. No generic realpath or symlink
|
|
50
|
+
// exception enters S5; physical HomesPath comes from the trusted native map.
|
|
51
|
+
suffix, ok := strings.CutPrefix(o.Home, "/var/services/homes/")
|
|
52
|
+
if !ok || suffix != actor.Username() || ValidateRelativeSegments([]string{suffix}, false) != "" {
|
|
53
|
+
return ErrUnsupported
|
|
54
|
+
}
|
|
55
|
+
w := readOnlyWork{RootPath: o.HomesPath, Action: ActionStat, Segments: []string{}}
|
|
56
|
+
if c := w.validate(); c != "" {
|
|
57
|
+
return c
|
|
58
|
+
}
|
|
59
|
+
return ""
|
|
60
|
+
}
|
|
61
|
+
if c = validate(before); c != "" {
|
|
62
|
+
return nil, c
|
|
63
|
+
}
|
|
64
|
+
pin, c := pinReadOnlyRoot(before.HomesPath + "/" + actor.Username())
|
|
65
|
+
if c != "" {
|
|
66
|
+
return nil, c
|
|
67
|
+
}
|
|
68
|
+
after, c := r.native.ObserveOwnHome(ctx, actor)
|
|
69
|
+
if c = nativeObservationCode(ctx, c); c == "" {
|
|
70
|
+
c = validate(after)
|
|
71
|
+
}
|
|
72
|
+
copyBefore, copyAfter := before, after
|
|
73
|
+
copyBefore.CheckedAt = time.Time{}
|
|
74
|
+
copyAfter.CheckedAt = time.Time{}
|
|
75
|
+
if c != "" || copyBefore != copyAfter {
|
|
76
|
+
pin.Close()
|
|
77
|
+
if c != "" {
|
|
78
|
+
return nil, c
|
|
79
|
+
}
|
|
80
|
+
return nil, ErrStale
|
|
81
|
+
}
|
|
82
|
+
// Bracket path/object continuity as well as native mapping metadata.
|
|
83
|
+
check, c := pinReadOnlyRoot(pin.path)
|
|
84
|
+
if c != "" {
|
|
85
|
+
pin.Close()
|
|
86
|
+
return nil, c
|
|
87
|
+
}
|
|
88
|
+
var first, second unix.Stat_t
|
|
89
|
+
same := unix.Fstat(int(pin.file.Fd()), &first) == nil && unix.Fstat(int(check.file.Fd()), &second) == nil && sameReadOnlyObject(first, second)
|
|
90
|
+
firstMount, mc := readOnlyMountID(int(pin.file.Fd()))
|
|
91
|
+
secondMount, nc := readOnlyMountID(int(check.file.Fd()))
|
|
92
|
+
same = same && mc == "" && nc == "" && firstMount == secondMount
|
|
93
|
+
check.Close()
|
|
94
|
+
if !same {
|
|
95
|
+
pin.Close()
|
|
96
|
+
return nil, ErrStale
|
|
97
|
+
}
|
|
98
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
99
|
+
pin.Close()
|
|
100
|
+
return nil, c
|
|
101
|
+
}
|
|
102
|
+
if !nativeFresh(after.CheckedAt, r.now()) || !nativeFresh(actor.account.CheckedAt, r.now()) {
|
|
103
|
+
pin.Close()
|
|
104
|
+
return nil, ErrStale
|
|
105
|
+
}
|
|
106
|
+
return pin, ""
|
|
107
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"os"
|
|
6
|
+
"testing"
|
|
7
|
+
"time"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
type homeNativeFake struct {
|
|
11
|
+
value ownHomeObservation
|
|
12
|
+
code Code
|
|
13
|
+
calls int
|
|
14
|
+
after func()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func (f *homeNativeFake) ObserveOwnHome(context.Context, NativeActor) (ownHomeObservation, Code) {
|
|
18
|
+
f.calls++
|
|
19
|
+
if f.after != nil {
|
|
20
|
+
f.after()
|
|
21
|
+
}
|
|
22
|
+
return f.value, f.code
|
|
23
|
+
}
|
|
24
|
+
func TestDSMHomeExistingOnlyAndBrackets(t *testing.T) {
|
|
25
|
+
p, _, _, c, now := nativeFixture()
|
|
26
|
+
actor, code := p.Resolve(context.Background(), c)
|
|
27
|
+
if code != "" {
|
|
28
|
+
t.Fatal(code)
|
|
29
|
+
}
|
|
30
|
+
root := t.TempDir()
|
|
31
|
+
if err := os.Mkdir(root+"/alice", 0700); err != nil {
|
|
32
|
+
t.Fatal(err)
|
|
33
|
+
}
|
|
34
|
+
native := &homeNativeFake{value: ownHomeObservation{Principal: actor.Principal(), SessionRef: actor.SessionRef(), Home: "/var/services/homes/alice", HomesPath: root, Enabled: true, ShareAllowed: true, VolumeProven: true, CheckedAt: now}}
|
|
35
|
+
resolver := &dsmOwnHomeResolver{native: native, now: func() time.Time { return now }}
|
|
36
|
+
pin, code := resolver.Resolve(context.Background(), actor)
|
|
37
|
+
if code != "" || native.calls != 2 {
|
|
38
|
+
t.Fatal(code, native.calls)
|
|
39
|
+
}
|
|
40
|
+
pin.Close()
|
|
41
|
+
for _, home := range []string{"/var/services/homes/bob", "/var/services/homes/../alice", "/volume1/arbitrary/alice"} {
|
|
42
|
+
native.value.Home = home
|
|
43
|
+
if pin, code = resolver.Resolve(context.Background(), actor); code == "" || pin != nil {
|
|
44
|
+
t.Fatal(home, code)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
native.value.Home = "/var/services/homes/alice"
|
|
48
|
+
os.Remove(root + "/alice")
|
|
49
|
+
if pin, code = resolver.Resolve(context.Background(), actor); code == "" || pin != nil {
|
|
50
|
+
t.Fatal("missing home accepted")
|
|
51
|
+
}
|
|
52
|
+
if _, err := os.Stat(root + "/alice"); !os.IsNotExist(err) {
|
|
53
|
+
t.Fatal("created missing home")
|
|
54
|
+
}
|
|
55
|
+
os.Symlink(root, root+"/alice")
|
|
56
|
+
if pin, code = resolver.Resolve(context.Background(), actor); code == "" || pin != nil {
|
|
57
|
+
t.Fatal("symlink accepted")
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
func TestDSMHomeUnknownAndChangedMappingRefuse(t *testing.T) {
|
|
61
|
+
p, _, _, c, now := nativeFixture()
|
|
62
|
+
actor, _ := p.Resolve(context.Background(), c)
|
|
63
|
+
for _, change := range []func(*ownHomeObservation){func(o *ownHomeObservation) { o.Enabled = false }, func(o *ownHomeObservation) { o.ShareAllowed = false }, func(o *ownHomeObservation) { o.VolumeProven = false }, func(o *ownHomeObservation) { o.CheckedAt = time.Time{} }, func(o *ownHomeObservation) { o.SessionRef = grantRef('e') }} {
|
|
64
|
+
f := &homeNativeFake{value: ownHomeObservation{Principal: actor.Principal(), SessionRef: actor.SessionRef(), Home: "/var/services/homes/alice", HomesPath: t.TempDir(), Enabled: true, ShareAllowed: true, VolumeProven: true, CheckedAt: now}}
|
|
65
|
+
change(&f.value)
|
|
66
|
+
pin, code := (&dsmOwnHomeResolver{native: f, now: func() time.Time { return now }}).Resolve(context.Background(), actor)
|
|
67
|
+
if code == "" || pin != nil {
|
|
68
|
+
t.Fatal("unknown metadata accepted")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
root := t.TempDir()
|
|
72
|
+
os.Mkdir(root+"/alice", 0700)
|
|
73
|
+
f := &homeNativeFake{value: ownHomeObservation{Principal: actor.Principal(), SessionRef: actor.SessionRef(), Home: "/var/services/homes/alice", HomesPath: root, Enabled: true, ShareAllowed: true, VolumeProven: true, CheckedAt: now}}
|
|
74
|
+
f.after = func() {
|
|
75
|
+
if f.calls == 2 {
|
|
76
|
+
f.value.ShareAllowed = false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if pin, code := (&dsmOwnHomeResolver{native: f, now: func() time.Time { return now }}).Resolve(context.Background(), actor); code == "" || pin != nil {
|
|
80
|
+
t.Fatal("changed observation leaked pin")
|
|
81
|
+
}
|
|
82
|
+
}
|