@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,516 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"crypto/rand"
|
|
6
|
+
"crypto/sha256"
|
|
7
|
+
"encoding/hex"
|
|
8
|
+
"encoding/json"
|
|
9
|
+
"math"
|
|
10
|
+
"slices"
|
|
11
|
+
"sync"
|
|
12
|
+
"time"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
type pendingConsent struct {
|
|
16
|
+
intent Intent
|
|
17
|
+
actor NativeActor
|
|
18
|
+
selection ConsentSelection
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// GrantAuthority is one supervisor's ordering owner. All reservations, confirms,
|
|
22
|
+
// revokes and Fence calls use this order. Native/ACL observations and cohort
|
|
23
|
+
// drain happen outside it. There is no process-global or helper RPC wiring yet.
|
|
24
|
+
type GrantAuthority struct {
|
|
25
|
+
mu *sync.Mutex
|
|
26
|
+
gate *admission
|
|
27
|
+
repository GrantRepository
|
|
28
|
+
native *NativeProvider
|
|
29
|
+
consent ConsentValidator
|
|
30
|
+
cohort GrantCohort
|
|
31
|
+
policy GrantPolicy
|
|
32
|
+
writes writeGates
|
|
33
|
+
fenced bool
|
|
34
|
+
intents map[string]pendingConsent
|
|
35
|
+
now func() time.Time
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// NewGrantAuthority reconciles before any admission, even when epoch/approval
|
|
39
|
+
// bytes match. Restart cannot prove account/scope continuity. There is no API
|
|
40
|
+
// to reactivate a suspended record or remove a tombstone; consent creates an ID.
|
|
41
|
+
func NewGrantAuthority(repository GrantRepository, native *NativeProvider, consent ConsentValidator, cohort GrantCohort) (*GrantAuthority, Code) {
|
|
42
|
+
if repository == nil {
|
|
43
|
+
return nil, ErrUnavailable
|
|
44
|
+
}
|
|
45
|
+
a := &GrantAuthority{mu: &sync.Mutex{}, repository: repository, native: native, consent: consent, cohort: cohort, intents: map[string]pendingConsent{}, now: time.Now}
|
|
46
|
+
c := repository.Transact(func(p GrantPolicy, s *GrantStore) (bool, Code) {
|
|
47
|
+
if !validGrantPolicy(p) {
|
|
48
|
+
return false, ErrIncompatible
|
|
49
|
+
}
|
|
50
|
+
a.policy = p
|
|
51
|
+
a.fenced = !p.Enabled
|
|
52
|
+
changed := false
|
|
53
|
+
for n := range s.Grants {
|
|
54
|
+
g := &s.Grants[n]
|
|
55
|
+
if g.State == GrantActive {
|
|
56
|
+
if g.Revision == math.MaxUint64 {
|
|
57
|
+
return false, ErrLimit
|
|
58
|
+
}
|
|
59
|
+
g.State = GrantSuspended
|
|
60
|
+
g.Reason = ErrSuspended
|
|
61
|
+
g.Revision++
|
|
62
|
+
changed = true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if changed {
|
|
66
|
+
if s.Revision == math.MaxUint64 {
|
|
67
|
+
return false, ErrLimit
|
|
68
|
+
}
|
|
69
|
+
s.Revision++
|
|
70
|
+
}
|
|
71
|
+
// Also initializes a missing authority snapshot; rewrites no active state.
|
|
72
|
+
return true, ""
|
|
73
|
+
})
|
|
74
|
+
if c != "" {
|
|
75
|
+
return nil, safeGrantCode(c)
|
|
76
|
+
}
|
|
77
|
+
if native != nil && native.managed != nil {
|
|
78
|
+
if c := native.managed.bind(a); c != "" {
|
|
79
|
+
return nil, c
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if native != nil && native.relaxed != nil {
|
|
83
|
+
if c := native.relaxed.bind(a); c != "" {
|
|
84
|
+
return nil, c
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return a, ""
|
|
88
|
+
}
|
|
89
|
+
func validGrantPolicy(p GrantPolicy) bool {
|
|
90
|
+
return p.Inventory.Valid() && p.Inventory.Protocol == DataProtocol && allReferences(p.Epoch, p.ApprovalBinding, p.CapabilityDigest)
|
|
91
|
+
}
|
|
92
|
+
func safeGrantCode(c Code) Code {
|
|
93
|
+
if c != "" && !c.Valid() {
|
|
94
|
+
return ErrUnavailable
|
|
95
|
+
}
|
|
96
|
+
return c
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Fence is sticky in memory and must precede the lifecycle owner's durable
|
|
100
|
+
// fence. New owner/epoch always starts with reconciliation, never clears this.
|
|
101
|
+
func (a *GrantAuthority) Fence() {
|
|
102
|
+
a.mu.Lock()
|
|
103
|
+
defer a.mu.Unlock()
|
|
104
|
+
a.fenced = true
|
|
105
|
+
clear(a.intents)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// transaction is called with the admission mutex held. A policy mismatch also
|
|
109
|
+
// fences the whole authority; it cannot adopt a new epoch on the fly.
|
|
110
|
+
func (a *GrantAuthority) transaction(fn func(*GrantStore) (bool, Code)) Code {
|
|
111
|
+
if a.gate != nil && !a.gate.allowLocked(a.now()) {
|
|
112
|
+
// A reload suspension refuses this call without revoking the authority.
|
|
113
|
+
if a.gate.blocked != "" {
|
|
114
|
+
a.fenced = true
|
|
115
|
+
clear(a.intents)
|
|
116
|
+
}
|
|
117
|
+
return ErrFenced
|
|
118
|
+
}
|
|
119
|
+
if a.fenced {
|
|
120
|
+
return ErrFenced
|
|
121
|
+
}
|
|
122
|
+
c := safeGrantCode(a.repository.Transact(func(p GrantPolicy, s *GrantStore) (bool, Code) {
|
|
123
|
+
if p != a.policy || !p.Enabled {
|
|
124
|
+
a.fenced = true
|
|
125
|
+
clear(a.intents)
|
|
126
|
+
return false, ErrFenced
|
|
127
|
+
}
|
|
128
|
+
return fn(s)
|
|
129
|
+
}))
|
|
130
|
+
if c == ErrCommitUncertain || c == ErrUnavailable || c == ErrInternal || c == ErrInvalid || c == ErrIncompatible {
|
|
131
|
+
a.fenced = true
|
|
132
|
+
clear(a.intents)
|
|
133
|
+
}
|
|
134
|
+
return c
|
|
135
|
+
}
|
|
136
|
+
func (a *GrantAuthority) actor(ctx context.Context, c SessionCarriers, old *NativeActor) (NativeActor, Code) {
|
|
137
|
+
if a.native == nil {
|
|
138
|
+
return NativeActor{}, ErrUnavailable
|
|
139
|
+
}
|
|
140
|
+
if old != nil {
|
|
141
|
+
return a.native.Revalidate(ctx, c, *old)
|
|
142
|
+
}
|
|
143
|
+
return a.native.Resolve(ctx, c)
|
|
144
|
+
}
|
|
145
|
+
func (a *GrantAuthority) selectConsent(ctx context.Context, actor NativeActor, candidate string, kind ScopeKind, actions []Action) (ConsentSelection, Code) {
|
|
146
|
+
if a.consent == nil {
|
|
147
|
+
return ConsentSelection{}, ErrUnavailable
|
|
148
|
+
}
|
|
149
|
+
selection, c := a.consent.ValidateConsent(ctx, actor, candidate, kind, slices.Clone(actions))
|
|
150
|
+
if c = nativeObservationCode(ctx, c); c != "" {
|
|
151
|
+
return ConsentSelection{}, c
|
|
152
|
+
}
|
|
153
|
+
if selection.Principal != actor.Principal() || selection.SessionRef != actor.SessionRef() || selection.Scope.Kind != kind {
|
|
154
|
+
return ConsentSelection{}, ErrDenied
|
|
155
|
+
}
|
|
156
|
+
if !nativeFresh(selection.CheckedAt, a.now()) {
|
|
157
|
+
return ConsentSelection{}, ErrStale
|
|
158
|
+
}
|
|
159
|
+
if !validContinuity(selection.Binding) {
|
|
160
|
+
return ConsentSelection{}, ErrSuspended
|
|
161
|
+
}
|
|
162
|
+
if selection.Binding.Epoch != a.policy.Epoch {
|
|
163
|
+
return ConsentSelection{}, ErrStale
|
|
164
|
+
}
|
|
165
|
+
// Reuse the strict authority shape validator for scope and action validation.
|
|
166
|
+
probe := Grant{Schema: GrantSchema, ID: candidate, Revision: 1, Inventory: a.policy.Inventory, ApprovalBinding: a.policy.ApprovalBinding, CapabilityDigest: a.policy.CapabilityDigest, Owner: actor.Principal(), Issuer: actor.Principal(), Scope: selection.Scope, Actions: actions, State: GrantActive, CreatedAt: a.now().UnixMilli(), LastValidated: selection.Binding}
|
|
167
|
+
if c := validateGrant(probe); c != "" {
|
|
168
|
+
return ConsentSelection{}, c
|
|
169
|
+
}
|
|
170
|
+
selection.Scope.Segments = slices.Clone(selection.Scope.Segments)
|
|
171
|
+
return selection, ""
|
|
172
|
+
}
|
|
173
|
+
func (a *GrantAuthority) Prepare(ctx context.Context, carriers SessionCarriers, candidate string, kind ScopeKind, actions []Action) (Intent, Code) {
|
|
174
|
+
if !allReferences(candidate) {
|
|
175
|
+
return Intent{}, ErrInvalid
|
|
176
|
+
}
|
|
177
|
+
if kind != ScopePersonal && kind != ScopeShared {
|
|
178
|
+
return Intent{}, ErrUnsupported
|
|
179
|
+
}
|
|
180
|
+
if c := validateGrantActions(actions); c != "" {
|
|
181
|
+
return Intent{}, c
|
|
182
|
+
}
|
|
183
|
+
for _, act := range actions {
|
|
184
|
+
if !act.ReadOnly() && !a.writes.allows(act) {
|
|
185
|
+
return Intent{}, ErrUnsupported
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
ctx, cancel := context.WithTimeout(ctx, MetadataTimeout)
|
|
189
|
+
defer cancel()
|
|
190
|
+
actor, c := a.actor(ctx, carriers, nil)
|
|
191
|
+
if c != "" {
|
|
192
|
+
return Intent{}, c
|
|
193
|
+
}
|
|
194
|
+
if kind == ScopeShared && !actor.Admin() {
|
|
195
|
+
return Intent{}, ErrDenied
|
|
196
|
+
}
|
|
197
|
+
selection, c := a.selectConsent(ctx, actor, candidate, kind, actions)
|
|
198
|
+
if c != "" {
|
|
199
|
+
return Intent{}, c
|
|
200
|
+
}
|
|
201
|
+
actor, c = a.actor(ctx, carriers, &actor)
|
|
202
|
+
if c != "" {
|
|
203
|
+
return Intent{}, c
|
|
204
|
+
}
|
|
205
|
+
a.mu.Lock()
|
|
206
|
+
defer a.mu.Unlock()
|
|
207
|
+
var intent Intent
|
|
208
|
+
c = a.transaction(func(_ *GrantStore) (bool, Code) {
|
|
209
|
+
now := a.now()
|
|
210
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
211
|
+
return false, c
|
|
212
|
+
}
|
|
213
|
+
if !nativeFresh(actor.account.CheckedAt, now) || !nativeFresh(selection.CheckedAt, now) {
|
|
214
|
+
return false, ErrStale
|
|
215
|
+
}
|
|
216
|
+
count := 0
|
|
217
|
+
for id, p := range a.intents {
|
|
218
|
+
if now.UnixMilli() >= p.intent.ExpiresAt {
|
|
219
|
+
delete(a.intents, id)
|
|
220
|
+
} else if p.intent.SubjectRef == actor.Principal().SubjectRef {
|
|
221
|
+
count++
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if count >= MaxLiveIntents || len(a.intents) >= MaxReplayEntries {
|
|
225
|
+
return false, ErrBusy
|
|
226
|
+
}
|
|
227
|
+
id, c := randomGrantID()
|
|
228
|
+
if c != "" {
|
|
229
|
+
return false, c
|
|
230
|
+
}
|
|
231
|
+
if _, exists := a.intents[id]; exists {
|
|
232
|
+
return false, ErrInternal
|
|
233
|
+
}
|
|
234
|
+
intent = Intent{ID: id, Inventory: a.policy.Inventory, Epoch: a.policy.Epoch, SubjectRef: actor.Principal().SubjectRef, SessionRef: actor.SessionRef(), CandidateID: candidate, ScopeKind: kind, Actions: slices.Clone(actions), SummaryDigest: consentDigest(a.policy, selection, actions), ExpiresAt: now.Add(IntentTTL).UnixMilli()}
|
|
235
|
+
a.intents[id] = pendingConsent{intent: intent, actor: actor, selection: selection}
|
|
236
|
+
return false, ""
|
|
237
|
+
})
|
|
238
|
+
if c != "" {
|
|
239
|
+
return Intent{}, c
|
|
240
|
+
}
|
|
241
|
+
intent.Actions = slices.Clone(intent.Actions)
|
|
242
|
+
return intent, ""
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// digest covers the exact scope/actor/session/action/approval/continuity summary;
|
|
246
|
+
// an observation timestamp refresh is not a scope change.
|
|
247
|
+
func consentDigest(policy GrantPolicy, s ConsentSelection, actions []Action) string {
|
|
248
|
+
s.CheckedAt = time.Time{}
|
|
249
|
+
b, _ := json.Marshal(struct {
|
|
250
|
+
Policy GrantPolicy
|
|
251
|
+
Selection ConsentSelection
|
|
252
|
+
Actions []Action
|
|
253
|
+
}{policy, s, actions})
|
|
254
|
+
sum := sha256.Sum256(b)
|
|
255
|
+
return hex.EncodeToString(sum[:])
|
|
256
|
+
}
|
|
257
|
+
func randomGrantID() (string, Code) {
|
|
258
|
+
var b [32]byte
|
|
259
|
+
if _, err := rand.Read(b[:]); err != nil {
|
|
260
|
+
return "", ErrUnavailable
|
|
261
|
+
}
|
|
262
|
+
return hex.EncodeToString(b[:]), ""
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
func (a *GrantAuthority) Confirm(ctx context.Context, carriers SessionCarriers, id, summary string, storeRevision uint64) (Grant, Code) {
|
|
266
|
+
if !allReferences(id, summary) || storeRevision == 0 {
|
|
267
|
+
return Grant{}, ErrInvalid
|
|
268
|
+
}
|
|
269
|
+
a.mu.Lock()
|
|
270
|
+
pending, ok := a.intents[id]
|
|
271
|
+
fenced := a.fenced
|
|
272
|
+
if ok && a.now().UnixMilli() >= pending.intent.ExpiresAt {
|
|
273
|
+
delete(a.intents, id)
|
|
274
|
+
a.mu.Unlock()
|
|
275
|
+
return Grant{}, ErrExpired
|
|
276
|
+
}
|
|
277
|
+
a.mu.Unlock()
|
|
278
|
+
if fenced {
|
|
279
|
+
return Grant{}, ErrFenced
|
|
280
|
+
}
|
|
281
|
+
if !ok {
|
|
282
|
+
return Grant{}, ErrReplay
|
|
283
|
+
}
|
|
284
|
+
if summary != pending.intent.SummaryDigest {
|
|
285
|
+
return Grant{}, ErrDenied
|
|
286
|
+
}
|
|
287
|
+
ctx, cancel := context.WithTimeout(ctx, MetadataTimeout)
|
|
288
|
+
defer cancel()
|
|
289
|
+
actor, c := a.actor(ctx, carriers, &pending.actor)
|
|
290
|
+
if c != "" {
|
|
291
|
+
return Grant{}, c
|
|
292
|
+
}
|
|
293
|
+
if pending.intent.ScopeKind == ScopeShared && !actor.Admin() {
|
|
294
|
+
return Grant{}, ErrDenied
|
|
295
|
+
}
|
|
296
|
+
selection, c := a.selectConsent(ctx, actor, pending.intent.CandidateID, pending.intent.ScopeKind, pending.intent.Actions)
|
|
297
|
+
if c != "" {
|
|
298
|
+
return Grant{}, c
|
|
299
|
+
}
|
|
300
|
+
actor, c = a.actor(ctx, carriers, &actor)
|
|
301
|
+
if c != "" {
|
|
302
|
+
return Grant{}, c
|
|
303
|
+
}
|
|
304
|
+
if consentDigest(a.policy, selection, pending.intent.Actions) != summary {
|
|
305
|
+
return Grant{}, ErrStale
|
|
306
|
+
}
|
|
307
|
+
a.mu.Lock()
|
|
308
|
+
defer a.mu.Unlock()
|
|
309
|
+
var grant Grant
|
|
310
|
+
c = a.transaction(func(s *GrantStore) (bool, Code) {
|
|
311
|
+
current, exists := a.intents[id]
|
|
312
|
+
if !exists {
|
|
313
|
+
return false, ErrReplay
|
|
314
|
+
}
|
|
315
|
+
now := a.now()
|
|
316
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
317
|
+
return false, c
|
|
318
|
+
}
|
|
319
|
+
if now.UnixMilli() >= current.intent.ExpiresAt {
|
|
320
|
+
delete(a.intents, id)
|
|
321
|
+
return false, ErrExpired
|
|
322
|
+
}
|
|
323
|
+
if !nativeFresh(actor.account.CheckedAt, now) || !nativeFresh(selection.CheckedAt, now) {
|
|
324
|
+
return false, ErrStale
|
|
325
|
+
}
|
|
326
|
+
if s.Revision != storeRevision {
|
|
327
|
+
return false, ErrStale
|
|
328
|
+
}
|
|
329
|
+
if len(s.Grants) >= MaxGrants || s.Revision == math.MaxUint64 {
|
|
330
|
+
return false, ErrLimit
|
|
331
|
+
}
|
|
332
|
+
newID, c := randomGrantID()
|
|
333
|
+
if c != "" {
|
|
334
|
+
return false, c
|
|
335
|
+
}
|
|
336
|
+
if findGrant(s, newID) != nil {
|
|
337
|
+
return false, ErrInternal
|
|
338
|
+
}
|
|
339
|
+
grant = Grant{Schema: GrantSchema, ID: newID, Revision: 1, Inventory: a.policy.Inventory, ApprovalBinding: a.policy.ApprovalBinding, CapabilityDigest: a.policy.CapabilityDigest, Owner: actor.Principal(), Issuer: actor.Principal(), Scope: selection.Scope, Actions: slices.Clone(pending.intent.Actions), State: GrantActive, CreatedAt: now.UnixMilli(), LastValidated: selection.Binding}
|
|
340
|
+
// Burn before committing. Failure/uncertainty never allows intent replay.
|
|
341
|
+
delete(a.intents, id)
|
|
342
|
+
s.Grants = append(s.Grants, cloneAuthorityGrant(grant))
|
|
343
|
+
s.Revision++
|
|
344
|
+
return true, ""
|
|
345
|
+
})
|
|
346
|
+
if c != "" {
|
|
347
|
+
return Grant{}, c
|
|
348
|
+
}
|
|
349
|
+
return grant, ""
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// WithGrantAdmission reserves an S2 slot while holding the shared ordering
|
|
353
|
+
// point and the short disk locks. reserve MUST be nonblocking and must not call
|
|
354
|
+
// back into authority. It executes no file operations in S3.
|
|
355
|
+
func (a *GrantAuthority) WithGrantAdmission(proof GrantAdmission, reserve func(Grant, NativeActor) Code) Code {
|
|
356
|
+
if !proof.Actor.valid || !nativeFresh(proof.Actor.account.CheckedAt, a.now()) {
|
|
357
|
+
return ErrDenied
|
|
358
|
+
}
|
|
359
|
+
if !allReferences(proof.GrantID) || proof.Revision == 0 || reserve == nil {
|
|
360
|
+
return ErrInvalid
|
|
361
|
+
}
|
|
362
|
+
if !proof.Action.ReadOnly() && !a.writes.allows(proof.Action) {
|
|
363
|
+
return ErrUnsupported
|
|
364
|
+
}
|
|
365
|
+
a.mu.Lock()
|
|
366
|
+
defer a.mu.Unlock()
|
|
367
|
+
if c := a.relaxedActorLocked(proof.Actor); c != "" {
|
|
368
|
+
return c
|
|
369
|
+
}
|
|
370
|
+
if proof.Actor.managed != nil {
|
|
371
|
+
m := proof.Actor.managed
|
|
372
|
+
if a.native == nil || a.native.managed != m || m.authority != a || !m.record.Enabled || proof.Actor.Principal().InstanceRef != m.record.Generation || proof.Actor.SessionRef() != m.record.SessionRef {
|
|
373
|
+
return ErrFenced
|
|
374
|
+
}
|
|
375
|
+
} else if a.native != nil && a.native.managed != nil {
|
|
376
|
+
return ErrDenied
|
|
377
|
+
}
|
|
378
|
+
suspended := false
|
|
379
|
+
suspensionAttempted := false
|
|
380
|
+
code := a.transaction(func(s *GrantStore) (bool, Code) {
|
|
381
|
+
if !nativeFresh(proof.Actor.account.CheckedAt, a.now()) {
|
|
382
|
+
return false, ErrStale
|
|
383
|
+
}
|
|
384
|
+
g := findGrant(s, proof.GrantID)
|
|
385
|
+
if g == nil {
|
|
386
|
+
return false, ErrDenied
|
|
387
|
+
}
|
|
388
|
+
if g.Scope.Kind == ScopePersonal && g.Owner != proof.Actor.Principal() {
|
|
389
|
+
return false, ErrDenied
|
|
390
|
+
}
|
|
391
|
+
if g.State == GrantRevoked {
|
|
392
|
+
return false, ErrRevoked
|
|
393
|
+
}
|
|
394
|
+
if g.Revision != proof.Revision {
|
|
395
|
+
return false, ErrStale
|
|
396
|
+
}
|
|
397
|
+
if g.State == GrantSuspended {
|
|
398
|
+
return false, ErrSuspended
|
|
399
|
+
}
|
|
400
|
+
if g.Inventory != a.policy.Inventory || g.ApprovalBinding != a.policy.ApprovalBinding || g.CapabilityDigest != a.policy.CapabilityDigest || g.EffectiveState(proof.Binding, proof.Continuous) != GrantActive {
|
|
401
|
+
suspensionAttempted = true
|
|
402
|
+
if g.Revision == math.MaxUint64 || s.Revision == math.MaxUint64 {
|
|
403
|
+
return false, ErrLimit
|
|
404
|
+
}
|
|
405
|
+
g.State = GrantSuspended
|
|
406
|
+
g.Reason = ErrSuspended
|
|
407
|
+
g.Revision++
|
|
408
|
+
s.Revision++
|
|
409
|
+
suspended = true
|
|
410
|
+
return true, ""
|
|
411
|
+
}
|
|
412
|
+
if !slices.Contains(g.Actions, proof.Action) {
|
|
413
|
+
return false, ErrDenied
|
|
414
|
+
}
|
|
415
|
+
return false, safeGrantCode(reserve(cloneAuthorityGrant(*g), proof.Actor))
|
|
416
|
+
})
|
|
417
|
+
if code != "" && suspensionAttempted {
|
|
418
|
+
a.fenced = true
|
|
419
|
+
clear(a.intents)
|
|
420
|
+
}
|
|
421
|
+
if code == "" && suspended {
|
|
422
|
+
return ErrSuspended
|
|
423
|
+
}
|
|
424
|
+
return code
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
func (a *GrantAuthority) Revoke(ctx context.Context, carriers SessionCarriers, id string, revision, storeRevision uint64) (RevokeResult, Code) {
|
|
428
|
+
if !allReferences(id) || revision == 0 || storeRevision == 0 {
|
|
429
|
+
return RevokeResult{}, ErrInvalid
|
|
430
|
+
}
|
|
431
|
+
actor, c := a.actor(ctx, carriers, nil)
|
|
432
|
+
if c != "" {
|
|
433
|
+
return RevokeResult{}, c
|
|
434
|
+
}
|
|
435
|
+
a.mu.Lock()
|
|
436
|
+
result := RevokeResult{}
|
|
437
|
+
key := GrantDrainKey{}
|
|
438
|
+
c = a.transaction(func(s *GrantStore) (bool, Code) {
|
|
439
|
+
if c := nativeContextCode(ctx); c != "" {
|
|
440
|
+
return false, c
|
|
441
|
+
}
|
|
442
|
+
if !nativeFresh(actor.account.CheckedAt, a.now()) {
|
|
443
|
+
return false, ErrStale
|
|
444
|
+
}
|
|
445
|
+
g := findGrant(s, id)
|
|
446
|
+
if g == nil {
|
|
447
|
+
return false, ErrDenied
|
|
448
|
+
}
|
|
449
|
+
if !actor.Admin() && (g.Scope.Kind != ScopePersonal || g.Owner != actor.Principal()) {
|
|
450
|
+
return false, ErrDenied
|
|
451
|
+
}
|
|
452
|
+
if s.Revision != storeRevision || g.Revision != revision {
|
|
453
|
+
return false, ErrStale
|
|
454
|
+
}
|
|
455
|
+
if g.State != GrantRevoked {
|
|
456
|
+
if g.Revision == math.MaxUint64 || s.Revision == math.MaxUint64 {
|
|
457
|
+
return false, ErrLimit
|
|
458
|
+
}
|
|
459
|
+
// Admission mutex provides memory deny through persistence. On any failure
|
|
460
|
+
// the whole owner is fenced; no new work sneaks through a failed R.
|
|
461
|
+
g.State = GrantRevoked
|
|
462
|
+
g.Reason = ErrRevoked
|
|
463
|
+
g.RevokedAt = max(g.CreatedAt, a.now().UnixMilli())
|
|
464
|
+
g.Revision++
|
|
465
|
+
s.Revision++
|
|
466
|
+
result = RevokeResult{GrantID: id, Revision: g.Revision}
|
|
467
|
+
key = GrantDrainKey{a.policy.Epoch, id, g.Revision}
|
|
468
|
+
return true, ""
|
|
469
|
+
}
|
|
470
|
+
result = RevokeResult{GrantID: id, Revision: g.Revision}
|
|
471
|
+
key = GrantDrainKey{a.policy.Epoch, id, g.Revision}
|
|
472
|
+
return false, ""
|
|
473
|
+
})
|
|
474
|
+
if c != "" && key.GrantID != "" {
|
|
475
|
+
a.fenced = true
|
|
476
|
+
clear(a.intents)
|
|
477
|
+
}
|
|
478
|
+
a.mu.Unlock()
|
|
479
|
+
// Best-effort stop after an uncertain/failed R; never claim durable R or Q.
|
|
480
|
+
if c != "" {
|
|
481
|
+
if key.GrantID != "" {
|
|
482
|
+
_, _ = a.drain(ctx, key)
|
|
483
|
+
}
|
|
484
|
+
return result, c
|
|
485
|
+
}
|
|
486
|
+
result.Revoked = true
|
|
487
|
+
proof, c := a.drain(ctx, key)
|
|
488
|
+
if c != "" {
|
|
489
|
+
return result, ErrCleanupRequired
|
|
490
|
+
}
|
|
491
|
+
a.mu.Lock()
|
|
492
|
+
defer a.mu.Unlock()
|
|
493
|
+
// Q is a separate durable artifact, not part of grants.json schema 1. Saving
|
|
494
|
+
// cannot resurrect authority and is allowed after a concurrent global fence.
|
|
495
|
+
c = safeGrantCode(a.repository.SaveQuiescence(proof))
|
|
496
|
+
if c != "" {
|
|
497
|
+
if c != ErrBusy {
|
|
498
|
+
a.fenced = true
|
|
499
|
+
}
|
|
500
|
+
return result, ErrCleanupRequired
|
|
501
|
+
}
|
|
502
|
+
result.Drained = true
|
|
503
|
+
return result, ""
|
|
504
|
+
}
|
|
505
|
+
func (a *GrantAuthority) drain(ctx context.Context, key GrantDrainKey) (GrantQuiescence, Code) {
|
|
506
|
+
if a.cohort == nil {
|
|
507
|
+
return GrantQuiescence{}, ErrCleanupRequired
|
|
508
|
+
}
|
|
509
|
+
ctx, cancel := context.WithTimeout(ctx, RevokeDrainTimeout)
|
|
510
|
+
defer cancel()
|
|
511
|
+
q, c := a.cohort.DrainGrant(ctx, key)
|
|
512
|
+
if c = nativeObservationCode(ctx, c); c != "" || q.Key != key || !completeQuiescence(q) {
|
|
513
|
+
return GrantQuiescence{}, ErrCleanupRequired
|
|
514
|
+
}
|
|
515
|
+
return q, ""
|
|
516
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
package helper
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"time"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// S3 is root-supervisor-owned. Only exact-owned-helper private RPC is wired;
|
|
9
|
+
// public helper sockets/CGI/generators expose no grant or data capability.
|
|
10
|
+
// Exactly one supervisor owns an authority for one epoch. Its admission order
|
|
11
|
+
// must also own S2 reservations and lifecycle fencing, not a helper-local mutex.
|
|
12
|
+
|
|
13
|
+
// GrantPolicy is derived under policy.lock from the current schema 2 approval.
|
|
14
|
+
// ApprovalBinding hashes the complete approval (including boot/install binding);
|
|
15
|
+
// CapabilityDigest pins the approved read-only registry ceiling.
|
|
16
|
+
type GrantPolicy struct {
|
|
17
|
+
Inventory Inventory
|
|
18
|
+
Epoch string
|
|
19
|
+
ApprovalBinding string
|
|
20
|
+
CapabilityDigest string
|
|
21
|
+
Enabled bool
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// GrantRepository runs only bounded local storage work. Lock order is the
|
|
25
|
+
// authority admission mutex -> policy.lock -> grants.lock. It decodes BOTH
|
|
26
|
+
// snapshots on every transaction. true requests a durable grant-only commit;
|
|
27
|
+
// two snapshots are never represented as one atomic transaction. Missing grants
|
|
28
|
+
// means an empty revision-1 store; malformed existing authority fails closed.
|
|
29
|
+
// A failed/uncertain commit must poison the repository until restart/reconcile.
|
|
30
|
+
type GrantRepository interface {
|
|
31
|
+
Transact(func(GrantPolicy, *GrantStore) (bool, Code)) Code
|
|
32
|
+
// SaveQuiescence durably records a complete proof only for a matching
|
|
33
|
+
// revoked ID/revision. It never changes or enables grant authority.
|
|
34
|
+
SaveQuiescence(GrantQuiescence) Code
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ConsentValidator is a trusted S1/S5 candidate/ACL/object adapter, not browser
|
|
38
|
+
// input. It rechecks current local mount, own-home/shared scope and action ACL.
|
|
39
|
+
// No implementation may persist carriers or touch NAS in S3 tests.
|
|
40
|
+
type ConsentValidator interface {
|
|
41
|
+
ValidateConsent(context.Context, NativeActor, string, ScopeKind, []Action) (ConsentSelection, Code)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type ConsentSelection struct {
|
|
45
|
+
Principal Principal
|
|
46
|
+
SessionRef string
|
|
47
|
+
Scope Scope
|
|
48
|
+
Binding ContinuityBinding
|
|
49
|
+
CheckedAt time.Time
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// GrantCohort is the S2 seam. Drain runs OUTSIDE admission and disk locks, with
|
|
53
|
+
// a <=2s observation deadline. It must close relay gates, cancel/reap all owned
|
|
54
|
+
// children, close leases/FDs and account for already admitted effects. Context
|
|
55
|
+
// cancellation, a signal, helper exit or transport EOF is never this proof.
|
|
56
|
+
type GrantCohort interface {
|
|
57
|
+
DrainGrant(context.Context, GrantDrainKey) (GrantQuiescence, Code)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type GrantDrainKey struct {
|
|
61
|
+
Epoch string
|
|
62
|
+
GrantID string
|
|
63
|
+
Revision uint64 // revoked revision; includes all earlier admissions for the ID
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type GrantQuiescence struct {
|
|
67
|
+
Cohort *GrantDrainProof `json:"cohort,omitempty"`
|
|
68
|
+
Key GrantDrainKey
|
|
69
|
+
ChildrenReaped bool
|
|
70
|
+
RelayClosed bool
|
|
71
|
+
LeasesClosed bool
|
|
72
|
+
FDsClosed bool
|
|
73
|
+
EffectsRecorded bool
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// GrantAdmission is a trusted in-memory use proof. S2/S5 must freshly establish
|
|
77
|
+
// App permission, actor identity/ACL and subject/scope continuity before this
|
|
78
|
+
// call; it is NOT a wire shape, a bearer capability or an ACL substitute.
|
|
79
|
+
// Reservation is nonblocking, never executes I/O, and registers the operation
|
|
80
|
+
// with the same supervisor cohort BEFORE releasing the admission order.
|
|
81
|
+
type GrantAdmission struct {
|
|
82
|
+
Actor NativeActor
|
|
83
|
+
GrantID string
|
|
84
|
+
Revision uint64
|
|
85
|
+
Action Action
|
|
86
|
+
Binding ContinuityBinding
|
|
87
|
+
Continuous bool
|
|
88
|
+
}
|