primitive-admin 1.2.0-alpha.1 → 1.2.0-alpha.11
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/README.md +105 -134
- package/assets/skill/skills/primitive-platform/SKILL.md +37 -4
- package/dist/bin/primitive.js +30 -35
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/agent-sessions.d.ts +133 -0
- package/dist/src/commands/agent-sessions.js +792 -0
- package/dist/src/commands/agent-sessions.js.map +1 -0
- package/dist/src/commands/analytics.js +0 -148
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps-children.d.ts +54 -0
- package/dist/src/commands/apps-children.js +631 -0
- package/dist/src/commands/apps-children.js.map +1 -0
- package/dist/src/commands/apps.d.ts +6 -0
- package/dist/src/commands/apps.js +131 -9
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth-sessions.d.ts +3 -3
- package/dist/src/commands/auth-sessions.js +117 -23
- package/dist/src/commands/auth-sessions.js.map +1 -1
- package/dist/src/commands/auth.js +460 -36
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/collections.js +316 -256
- package/dist/src/commands/collections.js.map +1 -1
- package/dist/src/commands/config.d.ts +1 -1
- package/dist/src/commands/config.js +60 -28
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/connections.js +11 -12
- package/dist/src/commands/connections.js.map +1 -1
- package/dist/src/commands/database-type-configs.js +2 -76
- package/dist/src/commands/database-type-configs.js.map +1 -1
- package/dist/src/commands/databases.d.ts +9 -0
- package/dist/src/commands/databases.js +221 -457
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/db3-types.d.ts +15 -0
- package/dist/src/commands/db3-types.js +157 -0
- package/dist/src/commands/db3-types.js.map +1 -0
- package/dist/src/commands/db3.d.ts +12 -0
- package/dist/src/commands/db3.js +1052 -0
- package/dist/src/commands/db3.js.map +1 -0
- package/dist/src/commands/documents.d.ts +121 -2
- package/dist/src/commands/documents.js +1601 -1251
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/env.d.ts +9 -1
- package/dist/src/commands/env.js +164 -49
- package/dist/src/commands/env.js.map +1 -1
- package/dist/src/commands/function-trigger-commands.d.ts +28 -0
- package/dist/src/commands/function-trigger-commands.js +341 -0
- package/dist/src/commands/function-trigger-commands.js.map +1 -0
- package/dist/src/commands/functions.js +297 -24
- package/dist/src/commands/functions.js.map +1 -1
- package/dist/src/commands/groups.js +150 -49
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.js +5 -5
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.js +23 -5
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.js +14 -8
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/metadata-category-configs.d.ts +2 -2
- package/dist/src/commands/metadata-category-configs.js +2 -2
- package/dist/src/commands/prompts.d.ts +7 -0
- package/dist/src/commands/prompts.js +48 -5
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/scripts.d.ts +9 -17
- package/dist/src/commands/scripts.js +24 -479
- package/dist/src/commands/scripts.js.map +1 -1
- package/dist/src/commands/sync-app-settings.d.ts +36 -8
- package/dist/src/commands/sync-app-settings.js +109 -23
- package/dist/src/commands/sync-app-settings.js.map +1 -1
- package/dist/src/commands/sync.d.ts +360 -610
- package/dist/src/commands/sync.js +3151 -6697
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.js +3 -3
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.js +77 -2
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/workflows.d.ts +5 -83
- package/dist/src/commands/workflows.js +57 -2282
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/aggregate-output.d.ts +25 -0
- package/dist/src/lib/aggregate-output.js +53 -0
- package/dist/src/lib/aggregate-output.js.map +1 -0
- package/dist/src/lib/api-client.d.ts +681 -551
- package/dist/src/lib/api-client.js +880 -814
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +47 -1
- package/dist/src/lib/app-settings-descriptor.js +114 -10
- package/dist/src/lib/app-settings-descriptor.js.map +1 -1
- package/dist/src/lib/auth-fixtures.d.ts +44 -0
- package/dist/src/lib/auth-fixtures.js +61 -0
- package/dist/src/lib/auth-fixtures.js.map +1 -0
- package/dist/src/lib/auth-flow.d.ts +41 -1
- package/dist/src/lib/auth-flow.js +70 -16
- package/dist/src/lib/auth-flow.js.map +1 -1
- package/dist/src/lib/block-layout.d.ts +12 -23
- package/dist/src/lib/block-layout.js +26 -92
- package/dist/src/lib/block-layout.js.map +1 -1
- package/dist/src/lib/block-selector.d.ts +2 -2
- package/dist/src/lib/block-selector.js +2 -2
- package/dist/src/lib/child-apps-local.d.ts +164 -0
- package/dist/src/lib/child-apps-local.js +258 -0
- package/dist/src/lib/child-apps-local.js.map +1 -0
- package/dist/src/lib/ci-session-request.d.ts +22 -0
- package/dist/src/lib/ci-session-request.js +51 -0
- package/dist/src/lib/ci-session-request.js.map +1 -0
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +10 -8
- package/dist/src/lib/codegen-shared/generatedFiles.js +21 -15
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
- package/dist/src/lib/codegen-shared/prettierStable.d.ts +1 -1
- package/dist/src/lib/codegen-shared/prettierStable.js +1 -1
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +2 -2
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +2 -2
- package/dist/src/lib/collection-export.d.ts +76 -15
- package/dist/src/lib/collection-export.js +116 -23
- package/dist/src/lib/collection-export.js.map +1 -1
- package/dist/src/lib/collection-principal.d.ts +22 -0
- package/dist/src/lib/collection-principal.js +35 -0
- package/dist/src/lib/collection-principal.js.map +1 -0
- package/dist/src/lib/config-object-descriptor.d.ts +3 -22
- package/dist/src/lib/config-object-descriptor.js +56 -290
- package/dist/src/lib/config-object-descriptor.js.map +1 -1
- package/dist/src/lib/config-payload.js +2 -3
- package/dist/src/lib/config-payload.js.map +1 -1
- package/dist/src/lib/config-surface.d.ts +5 -7
- package/dist/src/lib/config-surface.js +18 -40
- package/dist/src/lib/config-surface.js.map +1 -1
- package/dist/src/lib/connections-list.d.ts +10 -0
- package/dist/src/lib/connections-list.js +18 -0
- package/dist/src/lib/connections-list.js.map +1 -0
- package/dist/src/lib/credentials-home.d.ts +58 -0
- package/dist/src/lib/credentials-home.js +204 -0
- package/dist/src/lib/credentials-home.js.map +1 -0
- package/dist/src/lib/credentials-lock.d.ts +88 -0
- package/dist/src/lib/credentials-lock.js +302 -0
- package/dist/src/lib/credentials-lock.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +179 -24
- package/dist/src/lib/credentials-store.js +712 -77
- package/dist/src/lib/credentials-store.js.map +1 -1
- package/dist/src/lib/csv.d.ts +8 -9
- package/dist/src/lib/csv.js +3 -4
- package/dist/src/lib/csv.js.map +1 -1
- package/dist/src/lib/custodian.d.ts +8 -0
- package/dist/src/lib/custodian.js +18 -0
- package/dist/src/lib/custodian.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.js +5 -16
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
- package/dist/src/lib/db-codegen/dbNaming.d.ts +5 -13
- package/dist/src/lib/db-codegen/dbNaming.js +5 -17
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +7 -56
- package/dist/src/lib/db-codegen/dbTemplates.js +25 -125
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +2 -2
- package/dist/src/lib/db-codegen/dbTsTypes.js +2 -2
- package/dist/src/lib/db-codegen/dbTypeIR.d.ts +67 -2
- package/dist/src/lib/db-codegen/dbTypeIR.js +13 -2
- package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
- package/dist/src/lib/db3-export.d.ts +231 -0
- package/dist/src/lib/db3-export.js +510 -0
- package/dist/src/lib/db3-export.js.map +1 -0
- package/dist/src/lib/db3-index-output.d.ts +27 -0
- package/dist/src/lib/db3-index-output.js +49 -0
- package/dist/src/lib/db3-index-output.js.map +1 -0
- package/dist/src/lib/document-export-lookups.d.ts +31 -0
- package/dist/src/lib/document-export-lookups.js +53 -0
- package/dist/src/lib/document-export-lookups.js.map +1 -0
- package/dist/src/lib/document-export-permissions.d.ts +7 -5
- package/dist/src/lib/document-export-permissions.js +7 -5
- package/dist/src/lib/document-export-permissions.js.map +1 -1
- package/dist/src/lib/document-export-record-log.d.ts +57 -0
- package/dist/src/lib/document-export-record-log.js +215 -0
- package/dist/src/lib/document-export-record-log.js.map +1 -0
- package/dist/src/lib/document-ingest-artifact.d.ts +26 -2
- package/dist/src/lib/document-ingest-artifact.js +42 -8
- package/dist/src/lib/document-ingest-artifact.js.map +1 -1
- package/dist/src/lib/document-ingest-format2.d.ts +36 -0
- package/dist/src/lib/document-ingest-format2.js +78 -0
- package/dist/src/lib/document-ingest-format2.js.map +1 -0
- package/dist/src/lib/document-ingest-input.d.ts +9 -0
- package/dist/src/lib/document-ingest-input.js +28 -1
- package/dist/src/lib/document-ingest-input.js.map +1 -1
- package/dist/src/lib/document-ingest-rows.d.ts +16 -0
- package/dist/src/lib/document-ingest-rows.js +17 -0
- package/dist/src/lib/document-ingest-rows.js.map +1 -1
- package/dist/src/lib/document-ingest.d.ts +33 -1
- package/dist/src/lib/document-ingest.js +49 -0
- package/dist/src/lib/document-ingest.js.map +1 -1
- package/dist/src/lib/document-schema-rows.d.ts +42 -0
- package/dist/src/lib/document-schema-rows.js +53 -0
- package/dist/src/lib/document-schema-rows.js.map +1 -0
- package/dist/src/lib/env-resolver-core.d.ts +70 -2
- package/dist/src/lib/env-resolver-core.js +137 -20
- package/dist/src/lib/env-resolver-core.js.map +1 -1
- package/dist/src/lib/env-resolver.d.ts +14 -2
- package/dist/src/lib/env-resolver.js +32 -10
- package/dist/src/lib/env-resolver.js.map +1 -1
- package/dist/src/lib/function-authorize-check.d.ts +142 -0
- package/dist/src/lib/function-authorize-check.js +310 -0
- package/dist/src/lib/function-authorize-check.js.map +1 -0
- package/dist/src/lib/function-authorize-view.d.ts +15 -0
- package/dist/src/lib/function-authorize-view.js +50 -0
- package/dist/src/lib/function-authorize-view.js.map +1 -0
- package/dist/src/lib/function-bundle.d.ts +38 -18
- package/dist/src/lib/function-bundle.js +96 -35
- package/dist/src/lib/function-bundle.js.map +1 -1
- package/dist/src/lib/function-collect.d.ts +75 -12
- package/dist/src/lib/function-collect.js +427 -12
- package/dist/src/lib/function-collect.js.map +1 -1
- package/dist/src/lib/function-db-types.d.ts +29 -0
- package/dist/src/lib/function-db-types.js +117 -7
- package/dist/src/lib/function-db-types.js.map +1 -1
- package/dist/src/lib/function-document-types.d.ts +5 -3
- package/dist/src/lib/function-document-types.js +10 -14
- package/dist/src/lib/function-document-types.js.map +1 -1
- package/dist/src/lib/function-lint.d.ts +34 -0
- package/dist/src/lib/function-lint.js +112 -0
- package/dist/src/lib/function-lint.js.map +1 -0
- package/dist/src/lib/function-log-row.js +21 -2
- package/dist/src/lib/function-log-row.js.map +1 -1
- package/dist/src/lib/function-run.d.ts +16 -21
- package/dist/src/lib/function-run.js +37 -30
- package/dist/src/lib/function-run.js.map +1 -1
- package/dist/src/lib/function-schema-codegen.d.ts +1 -1
- package/dist/src/lib/function-schema-codegen.js +5 -5
- package/dist/src/lib/function-schema-codegen.js.map +1 -1
- package/dist/src/lib/function-source-roots.d.ts +67 -0
- package/dist/src/lib/function-source-roots.js +148 -0
- package/dist/src/lib/function-source-roots.js.map +1 -0
- package/dist/src/lib/function-sync.d.ts +108 -22
- package/dist/src/lib/function-sync.js +127 -39
- package/dist/src/lib/function-sync.js.map +1 -1
- package/dist/src/lib/function-trigger-listing.d.ts +11 -6
- package/dist/src/lib/function-trigger-listing.js +32 -11
- package/dist/src/lib/function-trigger-listing.js.map +1 -1
- package/dist/src/lib/function-typecheck.d.ts +37 -2
- package/dist/src/lib/function-typecheck.js +210 -28
- package/dist/src/lib/function-typecheck.js.map +1 -1
- package/dist/src/lib/function-versions.d.ts +2 -0
- package/dist/src/lib/function-versions.js +1 -0
- package/dist/src/lib/function-versions.js.map +1 -1
- package/dist/src/lib/generated-allowlist.js +0 -20
- package/dist/src/lib/generated-allowlist.js.map +1 -1
- package/dist/src/lib/generated-config-surfaces.d.ts +703 -203
- package/dist/src/lib/generated-config-surfaces.js +2270 -2014
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- package/dist/src/lib/generated-sdk-types.d.ts +1 -1
- package/dist/src/lib/generated-sdk-types.js +1 -1
- package/dist/src/lib/generated-sdk-types.js.map +1 -1
- package/dist/src/lib/init-adopt.js +12 -3
- package/dist/src/lib/init-adopt.js.map +1 -1
- package/dist/src/lib/init-login-note.d.ts +13 -0
- package/dist/src/lib/init-login-note.js +22 -0
- package/dist/src/lib/init-login-note.js.map +1 -0
- package/dist/src/lib/json-value.d.ts +6 -0
- package/dist/src/lib/json-value.js +13 -0
- package/dist/src/lib/json-value.js.map +1 -0
- package/dist/src/lib/load-routes.d.ts +33 -0
- package/dist/src/lib/load-routes.js +35 -0
- package/dist/src/lib/load-routes.js.map +1 -0
- package/dist/src/lib/local-state.d.ts +38 -7
- package/dist/src/lib/local-state.js +172 -49
- package/dist/src/lib/local-state.js.map +1 -1
- package/dist/src/lib/local-test-cases.d.ts +5 -2
- package/dist/src/lib/local-test-cases.js +7 -4
- package/dist/src/lib/local-test-cases.js.map +1 -1
- package/dist/src/lib/log-inspection.d.ts +42 -4
- package/dist/src/lib/log-inspection.js +37 -5
- package/dist/src/lib/log-inspection.js.map +1 -1
- package/dist/src/lib/login-exchange-check.d.ts +18 -0
- package/dist/src/lib/login-exchange-check.js +27 -0
- package/dist/src/lib/login-exchange-check.js.map +1 -0
- package/dist/src/lib/login-scope-lines.d.ts +25 -0
- package/dist/src/lib/login-scope-lines.js +45 -0
- package/dist/src/lib/login-scope-lines.js.map +1 -0
- package/dist/src/lib/logout-admin-session.d.ts +2 -1
- package/dist/src/lib/logout-admin-session.js +7 -1
- package/dist/src/lib/logout-admin-session.js.map +1 -1
- package/dist/src/lib/object-status-filter.d.ts +9 -1
- package/dist/src/lib/object-status-filter.js +9 -1
- package/dist/src/lib/object-status-filter.js.map +1 -1
- package/dist/src/lib/output.js +2 -0
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +0 -5
- package/dist/src/lib/paginate.js +0 -5
- package/dist/src/lib/paginate.js.map +1 -1
- package/dist/src/lib/pin-refusal-hint.d.ts +12 -0
- package/dist/src/lib/pin-refusal-hint.js +35 -0
- package/dist/src/lib/pin-refusal-hint.js.map +1 -0
- package/dist/src/lib/primitive-env-plugin.d.ts +99 -0
- package/dist/src/lib/primitive-env-plugin.js +408 -0
- package/dist/src/lib/primitive-env-plugin.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +7 -0
- package/dist/src/lib/project-config.js +22 -1
- package/dist/src/lib/project-config.js.map +1 -1
- package/dist/src/lib/project-login-apps.d.ts +8 -0
- package/dist/src/lib/project-login-apps.js +27 -0
- package/dist/src/lib/project-login-apps.js.map +1 -0
- package/dist/src/lib/prompt-schema-codegen.d.ts +10 -3
- package/dist/src/lib/prompt-schema-codegen.js +52 -11
- package/dist/src/lib/prompt-schema-codegen.js.map +1 -1
- package/dist/src/lib/pull-write.d.ts +31 -0
- package/dist/src/lib/pull-write.js +49 -0
- package/dist/src/lib/pull-write.js.map +1 -0
- package/dist/src/lib/push-failure-report.d.ts +45 -0
- package/dist/src/lib/push-failure-report.js +57 -0
- package/dist/src/lib/push-failure-report.js.map +1 -0
- package/dist/src/lib/records-verbs.d.ts +69 -0
- package/dist/src/lib/records-verbs.js +40 -0
- package/dist/src/lib/records-verbs.js.map +1 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +7 -0
- package/dist/src/lib/refresh-admin-credentials.js +16 -4
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
- package/dist/src/lib/root-import-decision.d.ts +65 -0
- package/dist/src/lib/root-import-decision.js +109 -0
- package/dist/src/lib/root-import-decision.js.map +1 -0
- package/dist/src/lib/run-status.d.ts +1 -1
- package/dist/src/lib/run-status.generated.d.ts +2 -2
- package/dist/src/lib/run-status.generated.js +3 -1
- package/dist/src/lib/run-status.generated.js.map +1 -1
- package/dist/src/lib/run-status.js +1 -1
- package/dist/src/lib/schema-codegen/generated-schema-descriptor.d.ts +129 -0
- package/dist/src/lib/schema-codegen/generated-schema-descriptor.js +269 -0
- package/dist/src/lib/schema-codegen/generated-schema-descriptor.js.map +1 -0
- package/dist/src/lib/schema-codegen/naming.d.ts +35 -0
- package/dist/src/lib/schema-codegen/naming.js +83 -0
- package/dist/src/lib/schema-codegen/naming.js.map +1 -0
- package/dist/src/lib/schema-codegen/schemaToTs.d.ts +82 -0
- package/dist/src/lib/schema-codegen/schemaToTs.js +305 -0
- package/dist/src/lib/schema-codegen/schemaToTs.js.map +1 -0
- package/dist/src/lib/scope-request.d.ts +84 -0
- package/dist/src/lib/scope-request.js +235 -0
- package/dist/src/lib/scope-request.js.map +1 -0
- package/dist/src/lib/session-id.d.ts +9 -0
- package/dist/src/lib/session-id.js +28 -0
- package/dist/src/lib/session-id.js.map +1 -0
- package/dist/src/lib/snapshot-build-rows.d.ts +21 -0
- package/dist/src/lib/snapshot-build-rows.js +22 -0
- package/dist/src/lib/snapshot-build-rows.js.map +1 -1
- package/dist/src/lib/snapshot-build.js +8 -3
- package/dist/src/lib/snapshot-build.js.map +1 -1
- package/dist/src/lib/snapshots.d.ts +17 -1
- package/dist/src/lib/snapshots.js +50 -2
- package/dist/src/lib/snapshots.js.map +1 -1
- package/dist/src/lib/swift-codegen/agentGenerator.d.ts +6 -2
- package/dist/src/lib/swift-codegen/agentGenerator.js +57 -5
- package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -1
- package/dist/src/lib/swift-codegen/banners.d.ts +34 -7
- package/dist/src/lib/swift-codegen/banners.js +37 -7
- package/dist/src/lib/swift-codegen/banners.js.map +1 -1
- package/dist/src/lib/swift-codegen/dbGenerator.d.ts +4 -3
- package/dist/src/lib/swift-codegen/dbGenerator.js +14 -117
- package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
- package/dist/src/lib/swift-codegen/functionGenerator.d.ts +3 -3
- package/dist/src/lib/swift-codegen/functionGenerator.js +23 -18
- package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
- package/dist/src/lib/swift-codegen/generator.d.ts +5 -5
- package/dist/src/lib/swift-codegen/generator.js +35 -40
- package/dist/src/lib/swift-codegen/generator.js.map +1 -1
- package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +3 -3
- package/dist/src/lib/swift-codegen/schemaToSwift.js +4 -4
- package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
- package/dist/src/lib/swift-codegen/swiftKeys.d.ts +19 -0
- package/dist/src/lib/swift-codegen/swiftKeys.js +31 -0
- package/dist/src/lib/swift-codegen/swiftKeys.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +35 -0
- package/dist/src/lib/sync-paths.js +57 -5
- package/dist/src/lib/sync-paths.js.map +1 -1
- package/dist/src/lib/sync-resource-types.d.ts +26 -26
- package/dist/src/lib/sync-resource-types.js +61 -189
- package/dist/src/lib/sync-resource-types.js.map +1 -1
- package/dist/src/lib/sync-selectors.d.ts +5 -1
- package/dist/src/lib/sync-selectors.js +23 -13
- package/dist/src/lib/sync-selectors.js.map +1 -1
- package/dist/src/lib/test-case-file-names.d.ts +3 -5
- package/dist/src/lib/test-case-file-names.js +3 -5
- package/dist/src/lib/test-case-file-names.js.map +1 -1
- package/dist/src/lib/toml-database-config.d.ts +15 -75
- package/dist/src/lib/toml-database-config.js +17 -306
- package/dist/src/lib/toml-database-config.js.map +1 -1
- package/dist/src/lib/transient-retry.d.ts +43 -0
- package/dist/src/lib/transient-retry.js +94 -0
- package/dist/src/lib/transient-retry.js.map +1 -0
- package/dist/src/lib/vars-override.d.ts +105 -0
- package/dist/src/lib/vars-override.js +143 -0
- package/dist/src/lib/vars-override.js.map +1 -0
- package/dist/src/lib/webhook-capture.d.ts +43 -0
- package/dist/src/lib/webhook-capture.js +91 -0
- package/dist/src/lib/webhook-capture.js.map +1 -0
- package/dist/src/lib/webhook-deliver.d.ts +18 -20
- package/dist/src/lib/webhook-deliver.js +34 -89
- package/dist/src/lib/webhook-deliver.js.map +1 -1
- package/dist/src/lib/webhook-test-run.d.ts +32 -0
- package/dist/src/lib/webhook-test-run.js +108 -0
- package/dist/src/lib/webhook-test-run.js.map +1 -0
- package/dist/src/lib/workflow-codegen/generator.d.ts +7 -7
- package/dist/src/lib/workflow-codegen/generator.js +16 -23
- package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
- package/dist/src/lib/workflow-codegen/invokerIR.d.ts +6 -12
- package/dist/src/lib/workflow-codegen/invokerIR.js +4 -5
- package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
- package/dist/src/lib/workflow-toml-validator.d.ts +2 -0
- package/dist/src/lib/workflow-toml-validator.js +28 -1
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- package/dist/src/types/index.d.ts +30 -37
- package/dist/src/validators.d.ts +7 -55
- package/dist/src/validators.js +7 -53
- package/dist/src/validators.js.map +1 -1
- package/dist/src/vite.d.ts +17 -0
- package/dist/src/vite.js +18 -0
- package/dist/src/vite.js.map +1 -0
- package/package.json +20 -12
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { loadCredentials, saveCredentials, clearCredentials, isTokenExpired,
|
|
2
|
-
import { allowGlobalCredentials } from "../lib/credentials-store.js";
|
|
1
|
+
import { loadCredentials, saveCredentials, clearCredentials, isTokenExpired, getConfiguredServerUrl, } from "../lib/config.js";
|
|
2
|
+
import { allowGlobalCredentials, allowGlobalCredentialsForServer, clearLeftoverLogins, environmentToken, getCredentialsFilePath, globalLoginCommand, isProjectMode, leftoverLogins, loginEnvironments, mismatchedLogin, partitionFromEnvironment, sameServer, worktreeLoginNotes, } from "../lib/credentials-store.js";
|
|
3
|
+
import { PrimitiveEnvError } from "../lib/env-resolver-core.js";
|
|
4
|
+
import { isCiToken } from "../lib/session-id.js";
|
|
3
5
|
import { browserLogin } from "../lib/auth-flow.js";
|
|
6
|
+
import { getCurrentEnvironment, getProjectConfig, requireCurrentEnvironment, } from "../lib/env-resolver.js";
|
|
7
|
+
import { buildScopeRequest } from "../lib/scope-request.js";
|
|
8
|
+
import { projectLoginApps } from "../lib/project-login-apps.js";
|
|
9
|
+
import { loginExchangeRefusal } from "../lib/login-exchange-check.js";
|
|
10
|
+
import { ApiClient, ApiError } from "../lib/api-client.js";
|
|
4
11
|
import { fetchWithTLS } from "../lib/fetch.js";
|
|
5
12
|
import { REFRESH_EXPIRED_MESSAGE, RefreshError, refreshAdminCredentials, } from "../lib/refresh-admin-credentials.js";
|
|
6
13
|
import { logoutAdminSession } from "../lib/logout-admin-session.js";
|
|
14
|
+
import { loginScopeLines } from "../lib/login-scope-lines.js";
|
|
7
15
|
import { registerAuthSessionsCommands } from "./auth-sessions.js";
|
|
16
|
+
import { outsideProjectServer } from "./apps.js";
|
|
8
17
|
import { success, error, info, keyValue, json } from "../lib/output.js";
|
|
9
18
|
function parseJwt(token) {
|
|
10
19
|
try {
|
|
@@ -19,6 +28,120 @@ function parseJwt(token) {
|
|
|
19
28
|
return {};
|
|
20
29
|
}
|
|
21
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether a project is in scope. A project config that cannot be read counts
|
|
33
|
+
* as one, so the command reports it exactly as it always has.
|
|
34
|
+
*/
|
|
35
|
+
function inProject() {
|
|
36
|
+
try {
|
|
37
|
+
return isProjectMode();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** The environment's app, or undefined outside a project. */
|
|
44
|
+
function environmentAppId() {
|
|
45
|
+
try {
|
|
46
|
+
return getCurrentEnvironment()?.config.appId;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The project a login runs in: its server and the apps of the committed
|
|
54
|
+
* environments on it (#4512). Undefined outside a project.
|
|
55
|
+
*/
|
|
56
|
+
function loginProject(serverUrl) {
|
|
57
|
+
const config = getProjectConfig();
|
|
58
|
+
return config ? { serverUrl, apps: projectLoginApps(config.environments, serverUrl) } : undefined;
|
|
59
|
+
}
|
|
60
|
+
/** The project a login's lines name (#4512); empty outside a project. */
|
|
61
|
+
function loginLinesContext(serverUrl) {
|
|
62
|
+
const config = getProjectConfig();
|
|
63
|
+
if (!config)
|
|
64
|
+
return {};
|
|
65
|
+
let signedIn = [];
|
|
66
|
+
try {
|
|
67
|
+
signedIn = loginEnvironments()?.environments ?? [];
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// The environments signed in are a courtesy; the login is stored.
|
|
71
|
+
}
|
|
72
|
+
return { serverUrl, environments: config.environments, signedIn };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The stored login on this server, or null; a scoped login builds on it.
|
|
76
|
+
* Never `PRIMITIVE_TOKEN`'s credentials (#3890): a login is not built on, nor
|
|
77
|
+
* saved beside, a CI job's token.
|
|
78
|
+
*/
|
|
79
|
+
function storedLogin(serverUrl) {
|
|
80
|
+
try {
|
|
81
|
+
const stored = loadCredentials();
|
|
82
|
+
return stored && stored.source !== "env" && stored.serverUrl === serverUrl ? stored : null;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The environments a login here signs in or out, when it is more than one:
|
|
90
|
+
* every environment of the project on the login's server (#4512), "dev,
|
|
91
|
+
* staging, feat". Null when the login is the current environment's alone.
|
|
92
|
+
*/
|
|
93
|
+
function sharedLoginEnvironments() {
|
|
94
|
+
let shared;
|
|
95
|
+
try {
|
|
96
|
+
shared = loginEnvironments();
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return shared && shared.environments.length > 1 ? shared.environments.join(", ") : null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Refuse a command that needs a login when there is none, saying why when a
|
|
105
|
+
* linked git worktree could not use the main worktree's (#4492).
|
|
106
|
+
*/
|
|
107
|
+
function refuseNotLoggedIn() {
|
|
108
|
+
error("Not logged in. Run 'primitive login' first.");
|
|
109
|
+
const hint = worktreeLoginNotes.notLoggedIn();
|
|
110
|
+
if (hint)
|
|
111
|
+
info(hint);
|
|
112
|
+
process.exit(2);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The last line of a login or logout in a linked git worktree that holds a
|
|
116
|
+
* credentials file of its own, which the shared login makes unused (#4492).
|
|
117
|
+
*/
|
|
118
|
+
function noteIgnoredCredentialsFile() {
|
|
119
|
+
const ignored = worktreeLoginNotes.ignoredFile();
|
|
120
|
+
if (ignored)
|
|
121
|
+
info(ignored);
|
|
122
|
+
}
|
|
123
|
+
/** The session id (`sid`) a stored access token carries. */
|
|
124
|
+
function sessionIdOf(credentials) {
|
|
125
|
+
const sid = credentials ? parseJwt(credentials.accessToken).sid : undefined;
|
|
126
|
+
return typeof sid === "string" && sid ? sid : undefined;
|
|
127
|
+
}
|
|
128
|
+
function stepUpFrom(exchange) {
|
|
129
|
+
return {
|
|
130
|
+
accessToken: exchange.accessToken,
|
|
131
|
+
expiresAt: exchange.expiresAt,
|
|
132
|
+
sessionId: exchange.sessionId ?? "",
|
|
133
|
+
scope: exchange.scope ?? [],
|
|
134
|
+
apps: exchange.apps ?? [],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function appsLabel(apps) {
|
|
138
|
+
return apps.length > 0 ? apps.join(", ") : "unpinned";
|
|
139
|
+
}
|
|
140
|
+
/** A stored step-up that has not expired, or null. */
|
|
141
|
+
function liveStepUp(credentials) {
|
|
142
|
+
const stepUp = credentials.stepUp;
|
|
143
|
+
return stepUp && new Date(stepUp.expiresAt).getTime() > Date.now() ? stepUp : null;
|
|
144
|
+
}
|
|
22
145
|
function readStdin() {
|
|
23
146
|
return new Promise((resolve, reject) => {
|
|
24
147
|
if (process.stdin.isTTY) {
|
|
@@ -32,18 +155,84 @@ function readStdin() {
|
|
|
32
155
|
process.stdin.on("error", reject);
|
|
33
156
|
});
|
|
34
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* `primitive token --scope …` (#3889): a token no wider than the stored login
|
|
160
|
+
* is derived headlessly; a wider one is approved in the browser. Either way
|
|
161
|
+
* only the token reaches stdout, and nothing is stored.
|
|
162
|
+
*
|
|
163
|
+
* `--step-up` (#4564) always goes to the browser: a derivation signs the
|
|
164
|
+
* stored login's own kind, so it could only print a token that is no step-up.
|
|
165
|
+
*/
|
|
166
|
+
async function printScopedToken(options) {
|
|
167
|
+
const credentials = loadCredentials();
|
|
168
|
+
const built = buildScopeRequest({
|
|
169
|
+
command: "token",
|
|
170
|
+
scope: options.scope,
|
|
171
|
+
app: options.app,
|
|
172
|
+
ttl: options.ttl,
|
|
173
|
+
stepUp: options.stepUp,
|
|
174
|
+
envAppId: environmentAppId(),
|
|
175
|
+
parentSid: sessionIdOf(credentials),
|
|
176
|
+
});
|
|
177
|
+
if ("message" in built) {
|
|
178
|
+
error(built.message);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
if (!credentials)
|
|
182
|
+
refuseNotLoggedIn();
|
|
183
|
+
const query = built.query;
|
|
184
|
+
const scope = query.scope.split(",");
|
|
185
|
+
const apps = query.apps ? query.apps.split(",") : [];
|
|
186
|
+
if (options.stepUp) {
|
|
187
|
+
info("A step-up needs your approval in the browser.");
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
try {
|
|
191
|
+
const derived = await new ApiClient().exchangeToken({
|
|
192
|
+
scope,
|
|
193
|
+
...(apps.length > 0 ? { apps } : {}),
|
|
194
|
+
...(options.ttl !== undefined ? { ttl: options.ttl } : {}),
|
|
195
|
+
});
|
|
196
|
+
console.log(derived.accessToken);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
if (!(err instanceof ApiError && err.code === "TOKEN_WIDER_THAN_PRESENTED")) {
|
|
201
|
+
error(err?.message || "Token exchange failed");
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
info("This token is wider than your login, so it needs your approval in the browser.");
|
|
206
|
+
}
|
|
207
|
+
const result = await browserLogin(credentials.serverUrl, {
|
|
208
|
+
query,
|
|
209
|
+
...(credentials.globalAdminAppId ? { partition: credentials.globalAdminAppId } : {}),
|
|
210
|
+
save: false,
|
|
211
|
+
});
|
|
212
|
+
if (!result.success || !result.exchange) {
|
|
213
|
+
error(`Token approval failed: ${result.error || "Unknown error"}`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
console.log(result.exchange.accessToken);
|
|
217
|
+
}
|
|
35
218
|
export function registerAuthCommands(program) {
|
|
36
219
|
// Login command
|
|
37
220
|
program
|
|
38
221
|
.command("login")
|
|
39
222
|
.description("Authenticate with the Primitive admin API via browser OAuth")
|
|
40
223
|
.option("--token-stdin", "Read a refresh token from stdin instead of browser OAuth")
|
|
224
|
+
.option("--scope <list>", "Ask for a scoped session (read, write, admin, data:read, data:write); a list with admin asks for a 15-minute step-up")
|
|
225
|
+
.option("--step-up", "Ask for a 15-minute step-up holding exactly --scope, stored beside your login (writes to a protected app need one)")
|
|
226
|
+
.option("--app <ids>", "Pin the session to these app ids (comma-separated), or all for every app; by default a login is pinned to the project's apps on its server and a step-up to the environment's app")
|
|
41
227
|
.action(async (options) => {
|
|
42
228
|
// Login is one of the four commands that may work with no project in
|
|
43
229
|
// scope (#3154, intent criterion 5): it is what CREATES the credentials
|
|
44
230
|
// a first `primitive init` then uses. Inside a project this changes
|
|
45
231
|
// nothing — the per-environment slot still answers.
|
|
46
232
|
allowGlobalCredentials();
|
|
233
|
+
if (environmentToken()) {
|
|
234
|
+
info("PRIMITIVE_TOKEN is set and takes precedence over this login while it is; unset it to use the login.");
|
|
235
|
+
}
|
|
47
236
|
// Resolve the target server from the active environment (project mode) or
|
|
48
237
|
// DEFAULT_SERVER_URL (legacy mode). Never a `-s/--server` flag — that was
|
|
49
238
|
// removed in #1343 because it always targeted prod regardless of --env.
|
|
@@ -57,6 +246,10 @@ export function registerAuthCommands(program) {
|
|
|
57
246
|
process.exit(1);
|
|
58
247
|
}
|
|
59
248
|
if (options.tokenStdin) {
|
|
249
|
+
if (options.scope !== undefined || options.app !== undefined || options.stepUp) {
|
|
250
|
+
error("--token-stdin takes no --scope, --app or --step-up: the token keeps the scope it was issued with.");
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
60
253
|
const refreshToken = (await readStdin()).trim();
|
|
61
254
|
if (!refreshToken) {
|
|
62
255
|
error("No token provided on stdin. Pipe a refresh token, e.g.:");
|
|
@@ -69,6 +262,7 @@ export function registerAuthCommands(program) {
|
|
|
69
262
|
// shared refresh helper. Only `serverUrl` and `refreshToken` are
|
|
70
263
|
// needed by the helper; the post-refresh response fills in the
|
|
71
264
|
// rest. (Codex cleanup #2 — issue #772.)
|
|
265
|
+
const partition = partitionFromEnvironment();
|
|
72
266
|
const seed = {
|
|
73
267
|
serverUrl,
|
|
74
268
|
accessToken: "",
|
|
@@ -77,9 +271,13 @@ export function registerAuthCommands(program) {
|
|
|
77
271
|
adminId: "",
|
|
78
272
|
email: "",
|
|
79
273
|
role: "admin",
|
|
274
|
+
...(partition ? { globalAdminAppId: partition } : {}),
|
|
80
275
|
};
|
|
81
276
|
const refreshed = await refreshAdminCredentials(seed);
|
|
82
277
|
const payload = parseJwt(refreshed.accessToken);
|
|
278
|
+
// As with a browser login, a step-up already stored stays usable
|
|
279
|
+
// (and revocable by logout) until it expires.
|
|
280
|
+
const existing = storedLogin(serverUrl);
|
|
83
281
|
const credentials = {
|
|
84
282
|
...refreshed,
|
|
85
283
|
adminId: payload.adminId || "",
|
|
@@ -87,15 +285,24 @@ export function registerAuthCommands(program) {
|
|
|
87
285
|
role: payload.role || "admin",
|
|
88
286
|
name: payload.name,
|
|
89
287
|
globalAdminAppId: payload.globalAdminAppId,
|
|
288
|
+
...(existing?.stepUp ? { stepUp: existing.stepUp } : {}),
|
|
90
289
|
};
|
|
91
290
|
saveCredentials(credentials);
|
|
92
291
|
success(`Logged in as ${credentials.email}`);
|
|
292
|
+
const shared = sharedLoginEnvironments();
|
|
293
|
+
if (shared)
|
|
294
|
+
info(`Signed in to: ${shared}`);
|
|
295
|
+
const storedElsewhere = worktreeLoginNotes.storedElsewhere();
|
|
296
|
+
if (storedElsewhere)
|
|
297
|
+
info(storedElsewhere);
|
|
93
298
|
if (credentials.role === "super-admin") {
|
|
94
299
|
info("You have super-admin privileges.");
|
|
95
300
|
}
|
|
301
|
+
noteIgnoredCredentialsFile();
|
|
96
302
|
}
|
|
97
303
|
catch (err) {
|
|
98
|
-
if (err instanceof RefreshError &&
|
|
304
|
+
if (err instanceof RefreshError &&
|
|
305
|
+
(err.code === "SESSION_REVOKED" || err.code === "SESSION_UNSCOPED")) {
|
|
99
306
|
error(err.message);
|
|
100
307
|
}
|
|
101
308
|
else if (err instanceof RefreshError) {
|
|
@@ -108,17 +315,69 @@ export function registerAuthCommands(program) {
|
|
|
108
315
|
}
|
|
109
316
|
return;
|
|
110
317
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
318
|
+
// #3889 — every login is approved in the browser. `--scope`/`--app`
|
|
319
|
+
// ask for a scoped session or an admin step-up; without `--app`, a
|
|
320
|
+
// login in a project is pinned to the project's apps on this server
|
|
321
|
+
// (#4512). The login this one builds on names the step-up's parent and
|
|
322
|
+
// the partition to exchange in.
|
|
323
|
+
const existing = storedLogin(serverUrl);
|
|
324
|
+
const built = buildScopeRequest({
|
|
325
|
+
command: "login",
|
|
326
|
+
scope: options.scope,
|
|
327
|
+
app: options.app,
|
|
328
|
+
stepUp: options.stepUp === true,
|
|
329
|
+
envAppId: environmentAppId(),
|
|
330
|
+
project: loginProject(serverUrl),
|
|
331
|
+
parentSid: sessionIdOf(existing),
|
|
332
|
+
});
|
|
333
|
+
if ("message" in built) {
|
|
334
|
+
error(built.message);
|
|
335
|
+
process.exit(1);
|
|
117
336
|
}
|
|
118
|
-
|
|
337
|
+
const partition = existing?.globalAdminAppId ?? partitionFromEnvironment();
|
|
338
|
+
const result = await browserLogin(serverUrl, {
|
|
339
|
+
...("query" in built ? { query: built.query } : {}),
|
|
340
|
+
...(partition ? { partition } : {}),
|
|
341
|
+
save: false,
|
|
342
|
+
});
|
|
343
|
+
if (!result.success || !result.credentials || !result.exchange) {
|
|
119
344
|
error(`Login failed: ${result.error || "Unknown error"}`);
|
|
120
345
|
process.exit(1);
|
|
121
346
|
}
|
|
347
|
+
// #4512 — a server older than this CLI mints every app for a pinned
|
|
348
|
+
// request; nothing is stored unless the session carries the pins asked for.
|
|
349
|
+
const refusal = "query" in built ? loginExchangeRefusal(built.query, result.exchange) : null;
|
|
350
|
+
if (refusal) {
|
|
351
|
+
error(refusal);
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
if (result.exchange.kind === "step-up" && existing) {
|
|
355
|
+
// The step-up sits beside the login; the login itself is unchanged.
|
|
356
|
+
const stepUp = stepUpFrom(result.exchange);
|
|
357
|
+
saveCredentials({ ...existing, stepUp });
|
|
358
|
+
success(`Step-up holding ${stepUp.scope.join(", ")} active until ${stepUp.expiresAt} (${appsLabel(stepUp.apps)}). A command refused for a step-up retries with it.`);
|
|
359
|
+
noteIgnoredCredentialsFile();
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
// A new login replaces the slot; a step-up already stored stays usable
|
|
363
|
+
// until it expires.
|
|
364
|
+
saveCredentials({
|
|
365
|
+
...result.credentials,
|
|
366
|
+
...(existing?.stepUp ? { stepUp: existing.stepUp } : {}),
|
|
367
|
+
});
|
|
368
|
+
success(`Logged in as ${result.credentials.email}`);
|
|
369
|
+
// #3891, #4512 — say what the login holds and reaches, every
|
|
370
|
+
// environment it signs in to and which need a login of their own, and
|
|
371
|
+
// how to step up for what it cannot do.
|
|
372
|
+
for (const line of loginScopeLines(result.exchange, loginLinesContext(serverUrl)))
|
|
373
|
+
info(line);
|
|
374
|
+
const storedElsewhere = worktreeLoginNotes.storedElsewhere();
|
|
375
|
+
if (storedElsewhere)
|
|
376
|
+
info(storedElsewhere);
|
|
377
|
+
if (result.credentials.role === "super-admin") {
|
|
378
|
+
info("You have super-admin privileges.");
|
|
379
|
+
}
|
|
380
|
+
noteIgnoredCredentialsFile();
|
|
122
381
|
});
|
|
123
382
|
// Bootstrap command - create first admin on empty database
|
|
124
383
|
program
|
|
@@ -134,6 +393,16 @@ export function registerAuthCommands(program) {
|
|
|
134
393
|
allowGlobalCredentials();
|
|
135
394
|
const serverUrl = options.server.replace(/\/$/, "");
|
|
136
395
|
try {
|
|
396
|
+
// Inside a project the login is stored in the current environment's
|
|
397
|
+
// slot, which only holds a login from that environment's server
|
|
398
|
+
// (#4492): refuse before an admin is created whose login could not be
|
|
399
|
+
// stored.
|
|
400
|
+
const env = getCurrentEnvironment();
|
|
401
|
+
if (env && !sameServer(serverUrl, env.config.apiUrl)) {
|
|
402
|
+
error(`"${env.name}" points at ${env.config.apiUrl}, not ${serverUrl}. Run bootstrap outside ` +
|
|
403
|
+
`a project, or from an environment that points at ${serverUrl}.`);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
137
406
|
const response = await fetchWithTLS(`${serverUrl}/admin/api/bootstrap`, {
|
|
138
407
|
method: "POST",
|
|
139
408
|
headers: { "Content-Type": "application/json" },
|
|
@@ -172,6 +441,17 @@ export function registerAuthCommands(program) {
|
|
|
172
441
|
// command fails: re-running it retries the revocation. A 401 means the
|
|
173
442
|
// stored token was already refused — nothing is left to revoke, so the
|
|
174
443
|
// credentials are cleared.
|
|
444
|
+
//
|
|
445
|
+
// #4512: every environment on a server uses the server's one login, so
|
|
446
|
+
// logout in any of them signs out all of them, and says which. A login an
|
|
447
|
+
// older CLI kept for another environment on the server (a leftover) is
|
|
448
|
+
// revoked too.
|
|
449
|
+
//
|
|
450
|
+
// #4492: a login whose slot records another server than the environment's
|
|
451
|
+
// is the one no other command uses. Logout revokes it at the server that
|
|
452
|
+
// issued it — the one that can — and says the environment is not signed in.
|
|
453
|
+
// In a linked git worktree the login is the main worktree's, so logout signs
|
|
454
|
+
// out every worktree that holds the project, and says so.
|
|
175
455
|
program
|
|
176
456
|
.command("logout")
|
|
177
457
|
.description("Revoke this login's admin session on the server and clear stored credentials")
|
|
@@ -180,14 +460,35 @@ export function registerAuthCommands(program) {
|
|
|
180
460
|
// would leave a global credentials file no command could clear
|
|
181
461
|
// (#3154, adjudicated finding F1).
|
|
182
462
|
allowGlobalCredentials();
|
|
183
|
-
|
|
184
|
-
|
|
463
|
+
// #3890 — a CI job's token is not a login to sign out of: its session
|
|
464
|
+
// is revoked by id, and nothing stored is touched.
|
|
465
|
+
if (environmentToken()) {
|
|
466
|
+
error("PRIMITIVE_TOKEN is set; revoke the CI session with `primitive auth sessions revoke <id>` instead.");
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
let credentials;
|
|
470
|
+
let issuedElsewhere = false;
|
|
471
|
+
try {
|
|
472
|
+
credentials = loadCredentials();
|
|
473
|
+
}
|
|
474
|
+
catch (err) {
|
|
475
|
+
if (!(err instanceof PrimitiveEnvError && err.kind === "server-mismatch"))
|
|
476
|
+
throw err;
|
|
477
|
+
credentials = mismatchedLogin();
|
|
478
|
+
issuedElsewhere = credentials !== null;
|
|
479
|
+
}
|
|
480
|
+
const leftovers = leftoverLogins();
|
|
481
|
+
if (!credentials && leftovers.length === 0) {
|
|
185
482
|
info("Not logged in.");
|
|
483
|
+
noteIgnoredCredentialsFile();
|
|
186
484
|
return;
|
|
187
485
|
}
|
|
188
|
-
let outcome;
|
|
486
|
+
let outcome = null;
|
|
189
487
|
try {
|
|
190
|
-
|
|
488
|
+
if (credentials)
|
|
489
|
+
outcome = await logoutAdminSession(credentials);
|
|
490
|
+
for (const leftover of leftovers)
|
|
491
|
+
await logoutAdminSession(leftover);
|
|
191
492
|
}
|
|
192
493
|
catch (err) {
|
|
193
494
|
error(`${err?.message || "Logout failed."} The session was NOT revoked, and ` +
|
|
@@ -195,15 +496,29 @@ export function registerAuthCommands(program) {
|
|
|
195
496
|
process.exit(1);
|
|
196
497
|
}
|
|
197
498
|
clearCredentials();
|
|
198
|
-
|
|
499
|
+
clearLeftoverLogins();
|
|
500
|
+
if (outcome?.kind === "already-invalid") {
|
|
199
501
|
success("Logged out. The stored session was already invalid on the server; local credentials cleared.");
|
|
200
502
|
}
|
|
201
|
-
else if (outcome.revoked.length > 0) {
|
|
503
|
+
else if (outcome && outcome.revoked.length > 0) {
|
|
202
504
|
success(`Logged out. Revoked session ${outcome.revoked.join(", ")}.`);
|
|
203
505
|
}
|
|
204
506
|
else {
|
|
205
507
|
success("Logged out successfully.");
|
|
206
508
|
}
|
|
509
|
+
if (issuedElsewhere && credentials) {
|
|
510
|
+
const env = getCurrentEnvironment();
|
|
511
|
+
info(`This login was issued by ${credentials.serverUrl}; "${env?.name}" now points at ` +
|
|
512
|
+
`${env?.config.apiUrl}, where you are not signed in.`);
|
|
513
|
+
}
|
|
514
|
+
const shared = sharedLoginEnvironments();
|
|
515
|
+
if (shared)
|
|
516
|
+
success(`Signed out of: ${shared}`);
|
|
517
|
+
const tree = loginEnvironments();
|
|
518
|
+
const sharedWorktrees = tree ? worktreeLoginNotes.sharedLogout(tree.tree) : null;
|
|
519
|
+
if (sharedWorktrees)
|
|
520
|
+
info(sharedWorktrees);
|
|
521
|
+
noteIgnoredCredentialsFile();
|
|
207
522
|
});
|
|
208
523
|
// Whoami command
|
|
209
524
|
//
|
|
@@ -212,34 +527,120 @@ export function registerAuthCommands(program) {
|
|
|
212
527
|
// about to act on?"); only the source moved, from a per-machine credentials
|
|
213
528
|
// slot to the one place that can name an app. Outside a project there is no
|
|
214
529
|
// environment and so no app, which is the honest answer there.
|
|
530
|
+
//
|
|
531
|
+
// #4918 — outside a project it reports the user and server a command run
|
|
532
|
+
// there would use: the server PRIMITIVE_SERVER_URL names, or production,
|
|
533
|
+
// and the global login only when that server issued it — the pin
|
|
534
|
+
// `apps delete` uses (#4905). Inside a project nothing here runs.
|
|
215
535
|
program
|
|
216
536
|
.command("whoami")
|
|
217
|
-
.description("Show
|
|
537
|
+
.description("Show the user, server and app a command run here would use")
|
|
218
538
|
.option("--json", "Output as JSON")
|
|
219
|
-
.action((options) => {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
539
|
+
.action(async (options) => {
|
|
540
|
+
const outside = inProject() ? null : outsideProjectServer();
|
|
541
|
+
let credentials;
|
|
542
|
+
if (outside !== null) {
|
|
543
|
+
allowGlobalCredentialsForServer(outside);
|
|
544
|
+
try {
|
|
545
|
+
credentials = loadCredentials();
|
|
546
|
+
}
|
|
547
|
+
catch (err) {
|
|
548
|
+
error(err.message);
|
|
549
|
+
process.exit(1);
|
|
550
|
+
}
|
|
551
|
+
if (!credentials) {
|
|
552
|
+
error(`Not logged in to ${outside}. Run '${globalLoginCommand(outside)} <app-id>' (or --app all) first.`);
|
|
553
|
+
process.exit(2);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
credentials = loadCredentials();
|
|
558
|
+
if (!credentials)
|
|
559
|
+
refuseNotLoggedIn();
|
|
560
|
+
}
|
|
561
|
+
const env = outside === null ? requireCurrentEnvironment() : null;
|
|
562
|
+
const app = env ? { appId: env.config.appId, appName: env.config.appName } : null;
|
|
563
|
+
const fromEnvironment = credentials.source === "env";
|
|
564
|
+
const serverSource = outside === null ? "environment" : process.env.PRIMITIVE_SERVER_URL?.trim() ? "PRIMITIVE_SERVER_URL" : "default";
|
|
565
|
+
const authSource = fromEnvironment ? "PRIMITIVE_TOKEN" : outside === null ? "project" : "global";
|
|
566
|
+
// #3889 — the session's kind, scope and pins, read from the stored
|
|
567
|
+
// token's claims, and the step-up held beside it. No request.
|
|
568
|
+
// #3890 — an opaque CI token in PRIMITIVE_TOKEN has no claims to read:
|
|
569
|
+
// the server says who it is, in one request.
|
|
570
|
+
let who;
|
|
571
|
+
let session;
|
|
572
|
+
if (fromEnvironment && isCiToken(credentials.accessToken)) {
|
|
573
|
+
try {
|
|
574
|
+
const me = (await new ApiClient().getMe());
|
|
575
|
+
who = { email: me.email, adminId: me.adminId, role: me.role };
|
|
576
|
+
session = me.session ?? null;
|
|
577
|
+
}
|
|
578
|
+
catch (err) {
|
|
579
|
+
error(err?.message || "Could not read the token's session.");
|
|
580
|
+
process.exit(1);
|
|
581
|
+
}
|
|
224
582
|
}
|
|
225
|
-
|
|
583
|
+
else {
|
|
584
|
+
const claims = parseJwt(credentials.accessToken);
|
|
585
|
+
who = fromEnvironment
|
|
586
|
+
? {
|
|
587
|
+
email: typeof claims.email === "string" ? claims.email : "",
|
|
588
|
+
adminId: typeof claims.adminId === "string" ? claims.adminId : "",
|
|
589
|
+
role: typeof claims.role === "string" ? claims.role : "",
|
|
590
|
+
}
|
|
591
|
+
: { email: credentials.email, adminId: credentials.adminId, role: credentials.role };
|
|
592
|
+
session = {
|
|
593
|
+
...(typeof claims.sid === "string" ? { sessionId: claims.sid } : {}),
|
|
594
|
+
kind: typeof claims.kind === "string" ? claims.kind : null,
|
|
595
|
+
scope: Array.isArray(claims.scope) ? claims.scope : "full",
|
|
596
|
+
apps: Array.isArray(claims.apps) ? claims.apps : [],
|
|
597
|
+
name: null,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
const kind = session?.kind ?? null;
|
|
601
|
+
const scope = session?.scope ?? "full";
|
|
602
|
+
const apps = session?.apps ?? [];
|
|
603
|
+
const stepUp = liveStepUp(credentials);
|
|
226
604
|
if (options.json) {
|
|
227
605
|
json({
|
|
228
|
-
email:
|
|
229
|
-
adminId:
|
|
230
|
-
role:
|
|
606
|
+
email: who.email,
|
|
607
|
+
adminId: who.adminId,
|
|
608
|
+
role: who.role,
|
|
231
609
|
serverUrl: credentials.serverUrl,
|
|
232
|
-
|
|
233
|
-
|
|
610
|
+
serverSource,
|
|
611
|
+
authSource,
|
|
612
|
+
environment: env?.name ?? null,
|
|
613
|
+
currentAppId: app ? app.appId : null,
|
|
614
|
+
currentAppName: app ? app.appName : null,
|
|
615
|
+
kind,
|
|
616
|
+
scope,
|
|
617
|
+
apps,
|
|
618
|
+
stepUp: stepUp
|
|
619
|
+
? { expiresAt: stepUp.expiresAt, scope: stepUp.scope, apps: stepUp.apps }
|
|
620
|
+
: null,
|
|
621
|
+
...(fromEnvironment ? { auth: "env", session } : {}),
|
|
234
622
|
});
|
|
235
623
|
return;
|
|
236
624
|
}
|
|
237
|
-
keyValue("Email",
|
|
238
|
-
keyValue("Admin ID",
|
|
239
|
-
keyValue("Role",
|
|
625
|
+
keyValue("Email", who.email);
|
|
626
|
+
keyValue("Admin ID", who.adminId);
|
|
627
|
+
keyValue("Role", who.role);
|
|
628
|
+
if (env)
|
|
629
|
+
keyValue("Environment", env.name);
|
|
240
630
|
keyValue("Server", credentials.serverUrl);
|
|
241
|
-
|
|
242
|
-
|
|
631
|
+
keyValue("Server Source", env ? `environment "${env.name}"` : serverSource);
|
|
632
|
+
keyValue("Current App", app ? app.appName || app.appId : "none (pass --app)");
|
|
633
|
+
if (fromEnvironment)
|
|
634
|
+
keyValue("Auth", "PRIMITIVE_TOKEN");
|
|
635
|
+
else if (!env)
|
|
636
|
+
keyValue("Auth", `global login (${getCredentialsFilePath()})`);
|
|
637
|
+
keyValue("Kind", kind);
|
|
638
|
+
if (session?.name)
|
|
639
|
+
keyValue("Name", session.name);
|
|
640
|
+
keyValue("Scope", scope === "full" ? "full" : scope.join(", "));
|
|
641
|
+
keyValue("Apps", appsLabel(apps));
|
|
642
|
+
if (stepUp) {
|
|
643
|
+
keyValue("Step-up", `active until ${stepUp.expiresAt}, scope ${stepUp.scope.join(", ")}, ${appsLabel(stepUp.apps)}`);
|
|
243
644
|
}
|
|
244
645
|
});
|
|
245
646
|
// Token command - print access token for scripting
|
|
@@ -258,11 +659,34 @@ export function registerAuthCommands(program) {
|
|
|
258
659
|
.command("token")
|
|
259
660
|
.description("Print the current access token (for scripting)")
|
|
260
661
|
.option("--refresh", "Print the refresh token instead of the access token")
|
|
662
|
+
.option("--scope <list>", "Print a token with only these scopes; one wider than your login is approved in the browser and cannot be refreshed")
|
|
663
|
+
.option("--step-up", "Print a 15-minute step-up holding exactly --scope, always approved in the browser")
|
|
664
|
+
.option("--app <ids>", "Pin the printed token to these app ids (comma-separated), or all for an unpinned one")
|
|
665
|
+
.option("--ttl <d>", "Lifetime of the printed token, such as 15m (at most 1h; 15m for a step-up)")
|
|
261
666
|
.action(async (options) => {
|
|
667
|
+
if (options.scope !== undefined ||
|
|
668
|
+
options.app !== undefined ||
|
|
669
|
+
options.ttl !== undefined ||
|
|
670
|
+
options.stepUp) {
|
|
671
|
+
if (options.refresh) {
|
|
672
|
+
error("--refresh prints the stored refresh token; it takes no --scope, --app, --ttl or --step-up.");
|
|
673
|
+
process.exit(1);
|
|
674
|
+
}
|
|
675
|
+
await printScopedToken(options);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
262
678
|
const credentials = loadCredentials();
|
|
263
|
-
if (!credentials)
|
|
264
|
-
|
|
265
|
-
|
|
679
|
+
if (!credentials)
|
|
680
|
+
refuseNotLoggedIn();
|
|
681
|
+
// #3890 — the token in PRIMITIVE_TOKEN is printed as it is; it has no
|
|
682
|
+
// refresh token and is never refreshed here.
|
|
683
|
+
if (credentials.source === "env") {
|
|
684
|
+
if (options.refresh) {
|
|
685
|
+
error("PRIMITIVE_TOKEN has no refresh token.");
|
|
686
|
+
process.exit(1);
|
|
687
|
+
}
|
|
688
|
+
console.log(credentials.accessToken);
|
|
689
|
+
return;
|
|
266
690
|
}
|
|
267
691
|
if (options.refresh) {
|
|
268
692
|
// Dumb-print contract preserved — see Fork 4 in the design doc.
|