@seliseblocks/cli-os 0.1.4 → 0.1.5
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/AI_USAGE_GUIDE.md +328 -58
- package/README.md +83 -46
- package/dist/commands/auth/client-credentials/delete.d.ts +1 -0
- package/dist/commands/auth/client-credentials/delete.js +23 -0
- package/dist/commands/auth/client-credentials/list.d.ts +1 -0
- package/dist/commands/auth/client-credentials/list.js +14 -0
- package/dist/commands/auth/client-credentials/save.d.ts +1 -0
- package/dist/commands/auth/client-credentials/save.js +41 -0
- package/dist/commands/auth/config/get.d.ts +1 -0
- package/dist/commands/auth/config/get.js +14 -0
- package/dist/commands/auth/config/save.d.ts +1 -0
- package/dist/commands/auth/config/save.js +37 -0
- package/dist/commands/auth/idp/create.d.ts +1 -0
- package/dist/commands/auth/idp/create.js +46 -0
- package/dist/commands/auth/idp/delete.d.ts +1 -0
- package/dist/commands/auth/idp/delete.js +23 -0
- package/dist/commands/auth/idp/get.d.ts +1 -0
- package/dist/commands/auth/idp/get.js +16 -0
- package/dist/commands/auth/idp/list.d.ts +1 -0
- package/dist/commands/auth/idp/list.js +14 -0
- package/dist/commands/auth/idp/status.d.ts +1 -0
- package/dist/commands/auth/idp/status.js +27 -0
- package/dist/commands/auth/idp/update.d.ts +7 -0
- package/dist/commands/auth/idp/update.js +45 -0
- package/dist/commands/auth/oidc-clients/delete.d.ts +1 -0
- package/dist/commands/auth/oidc-clients/delete.js +23 -0
- package/dist/commands/auth/oidc-clients/get.d.ts +1 -0
- package/dist/commands/auth/oidc-clients/get.js +16 -0
- package/dist/commands/auth/oidc-clients/list.d.ts +1 -0
- package/dist/commands/auth/oidc-clients/list.js +14 -0
- package/dist/commands/auth/oidc-clients/rotate-secret.d.ts +1 -0
- package/dist/commands/auth/oidc-clients/rotate-secret.js +23 -0
- package/dist/commands/auth/oidc-clients/save.d.ts +2 -0
- package/dist/commands/auth/oidc-clients/save.js +57 -0
- package/dist/commands/auth/refresh.js +1 -1
- package/dist/commands/data/config/create.d.ts +1 -0
- package/dist/commands/data/config/create.js +38 -0
- package/dist/commands/data/config/get.d.ts +1 -0
- package/dist/commands/data/config/get.js +14 -0
- package/dist/commands/data/config/update.d.ts +1 -0
- package/dist/commands/data/config/update.js +41 -0
- package/dist/commands/data/files/create-folder.d.ts +1 -0
- package/dist/commands/data/files/create-folder.js +34 -0
- package/dist/commands/data/files/delete-folder.d.ts +1 -0
- package/dist/commands/data/files/delete-folder.js +25 -0
- package/dist/commands/data/files/delete.d.ts +1 -0
- package/dist/commands/data/files/delete.js +28 -0
- package/dist/commands/data/files/dms-list.d.ts +1 -0
- package/dist/commands/data/files/dms-list.js +27 -0
- package/dist/commands/data/files/dms-upload.d.ts +6 -0
- package/dist/commands/data/files/dms-upload.js +41 -0
- package/dist/commands/data/files/get-many.d.ts +1 -0
- package/dist/commands/data/files/get-many.js +24 -0
- package/dist/commands/data/files/get.d.ts +1 -0
- package/dist/commands/data/files/get.js +21 -0
- package/dist/commands/data/files/info.d.ts +1 -0
- package/dist/commands/data/files/info.js +30 -0
- package/dist/commands/data/files/presigned-upload-url.d.ts +6 -0
- package/dist/commands/data/files/presigned-upload-url.js +34 -0
- package/dist/commands/data/files/update-additional-info.d.ts +1 -0
- package/dist/commands/data/files/update-additional-info.js +26 -0
- package/dist/commands/data/files/upload-to-local-storage.d.ts +5 -0
- package/dist/commands/data/files/upload-to-local-storage.js +55 -0
- package/dist/commands/data/files/upload-to-url.d.ts +8 -0
- package/dist/commands/data/files/upload-to-url.js +36 -0
- package/dist/commands/data/files/upload.d.ts +7 -0
- package/dist/commands/data/files/upload.js +145 -0
- package/dist/commands/data/rules/policy/delete.d.ts +1 -0
- package/dist/commands/data/rules/policy/delete.js +24 -0
- package/dist/commands/data/rules/policy/get.d.ts +1 -0
- package/dist/commands/data/rules/policy/get.js +17 -0
- package/dist/commands/data/schema/aggregation.d.ts +1 -0
- package/dist/commands/data/schema/aggregation.js +26 -0
- package/dist/commands/data/schema/change-logs.d.ts +1 -0
- package/dist/commands/data/schema/change-logs.js +14 -0
- package/dist/commands/data/schema/delete.d.ts +1 -0
- package/dist/commands/data/schema/delete.js +24 -0
- package/dist/commands/data/schema/fields.d.ts +5 -0
- package/dist/commands/data/schema/fields.js +39 -0
- package/dist/commands/data/schema/get-by-name.d.ts +1 -0
- package/dist/commands/data/schema/get-by-name.js +17 -0
- package/dist/commands/data/schema/get.d.ts +1 -0
- package/dist/commands/data/schema/get.js +17 -0
- package/dist/commands/data/schema/info/list.d.ts +1 -0
- package/dist/commands/data/schema/info/list.js +15 -0
- package/dist/commands/data/schema/info/save.d.ts +1 -0
- package/dist/commands/data/schema/info/save.js +34 -0
- package/dist/commands/data/schema/info/update.d.ts +1 -0
- package/dist/commands/data/schema/info/update.js +35 -0
- package/dist/commands/data/sync.d.ts +7 -0
- package/dist/commands/data/sync.js +46 -0
- package/dist/commands/data/validation/by-schema-field.d.ts +1 -0
- package/dist/commands/data/validation/by-schema-field.js +18 -0
- package/dist/commands/data/validation/by-schema.d.ts +1 -0
- package/dist/commands/data/validation/by-schema.js +17 -0
- package/dist/commands/data/validation/delete.d.ts +1 -0
- package/dist/commands/data/validation/delete.js +24 -0
- package/dist/commands/data/validation/get.d.ts +1 -0
- package/dist/commands/data/validation/get.js +17 -0
- package/dist/commands/data/validation/list.d.ts +1 -0
- package/dist/commands/data/validation/list.js +25 -0
- package/dist/commands/data/validation/save.d.ts +6 -0
- package/dist/commands/data/validation/save.js +44 -0
- package/dist/commands/deselect.js +1 -1
- package/dist/commands/iam/email/available.d.ts +1 -0
- package/dist/commands/iam/email/available.js +17 -0
- package/dist/commands/iam/organizations/config-get.d.ts +1 -0
- package/dist/commands/iam/organizations/config-get.js +14 -0
- package/dist/commands/iam/organizations/config-save.d.ts +1 -0
- package/dist/commands/iam/organizations/config-save.js +34 -0
- package/dist/commands/iam/organizations/create.d.ts +1 -0
- package/dist/commands/iam/organizations/create.js +37 -0
- package/dist/commands/iam/organizations/get.d.ts +1 -0
- package/dist/commands/iam/organizations/get.js +16 -0
- package/dist/commands/iam/organizations/list.d.ts +1 -0
- package/dist/commands/iam/organizations/list.js +26 -0
- package/dist/commands/iam/organizations/my.d.ts +1 -0
- package/dist/commands/iam/organizations/my.js +14 -0
- package/dist/commands/iam/organizations/update.d.ts +1 -0
- package/dist/commands/iam/organizations/update.js +39 -0
- package/dist/commands/iam/permissions/by-severity.d.ts +1 -0
- package/dist/commands/iam/permissions/by-severity.js +14 -0
- package/dist/commands/iam/permissions/create.d.ts +1 -0
- package/dist/commands/iam/permissions/create.js +39 -0
- package/dist/commands/iam/permissions/get.d.ts +1 -0
- package/dist/commands/iam/permissions/get.js +16 -0
- package/dist/commands/iam/permissions/list.d.ts +1 -0
- package/dist/commands/iam/permissions/list.js +41 -0
- package/dist/commands/iam/permissions/update.d.ts +1 -0
- package/dist/commands/iam/permissions/update.js +40 -0
- package/dist/commands/iam/resources/features.d.ts +1 -0
- package/dist/commands/iam/resources/features.js +19 -0
- package/dist/commands/iam/resources/groups.d.ts +1 -0
- package/dist/commands/iam/resources/groups.js +14 -0
- package/dist/commands/iam/roles/assign-permissions.d.ts +1 -0
- package/dist/commands/iam/roles/assign-permissions.js +33 -0
- package/dist/commands/iam/roles/assignable.d.ts +1 -0
- package/dist/commands/iam/roles/assignable.js +14 -0
- package/dist/commands/iam/roles/create.d.ts +1 -0
- package/dist/commands/iam/roles/create.js +35 -0
- package/dist/commands/iam/roles/get.d.ts +1 -0
- package/dist/commands/iam/roles/get.js +16 -0
- package/dist/commands/iam/roles/list.d.ts +1 -0
- package/dist/commands/iam/roles/list.js +34 -0
- package/dist/commands/iam/roles/update.d.ts +1 -0
- package/dist/commands/iam/roles/update.js +35 -0
- package/dist/commands/iam/signup-settings/get.d.ts +1 -0
- package/dist/commands/iam/signup-settings/get.js +14 -0
- package/dist/commands/iam/signup-settings/save.d.ts +1 -0
- package/dist/commands/iam/signup-settings/save.js +32 -0
- package/dist/commands/iam/users/access-grant.d.ts +1 -0
- package/dist/commands/iam/users/access-grant.js +32 -0
- package/dist/commands/iam/users/access-revoke.d.ts +1 -0
- package/dist/commands/iam/users/access-revoke.js +24 -0
- package/dist/commands/iam/users/activate.d.ts +1 -0
- package/dist/commands/iam/users/activate.js +24 -0
- package/dist/commands/iam/users/create.d.ts +1 -0
- package/dist/commands/iam/users/create.js +39 -0
- package/dist/commands/iam/users/deactivate.d.ts +1 -0
- package/dist/commands/iam/users/deactivate.js +24 -0
- package/dist/commands/iam/users/exists.d.ts +1 -0
- package/dist/commands/iam/users/exists.js +17 -0
- package/dist/commands/iam/users/get.d.ts +1 -0
- package/dist/commands/iam/users/get.js +17 -0
- package/dist/commands/iam/users/list.d.ts +1 -0
- package/dist/commands/iam/users/list.js +34 -0
- package/dist/commands/iam/users/update.d.ts +1 -0
- package/dist/commands/iam/users/update.js +35 -0
- package/dist/commands/init.js +0 -12
- package/dist/commands/localization/assistant/translation-suggestion.d.ts +1 -0
- package/dist/commands/localization/assistant/translation-suggestion.js +35 -0
- package/dist/commands/localization/config/get-webhook.d.ts +1 -0
- package/dist/commands/localization/config/get-webhook.js +14 -0
- package/dist/commands/localization/config/save-webhook.d.ts +1 -0
- package/dist/commands/localization/config/save-webhook.js +47 -0
- package/dist/commands/localization/glossary/delete.d.ts +1 -0
- package/dist/commands/localization/glossary/delete.js +24 -0
- package/dist/commands/localization/glossary/get.d.ts +1 -0
- package/dist/commands/localization/glossary/get.js +17 -0
- package/dist/commands/localization/glossary/list.d.ts +1 -0
- package/dist/commands/localization/glossary/list.js +22 -0
- package/dist/commands/localization/glossary/save.d.ts +1 -0
- package/dist/commands/localization/glossary/save.js +38 -0
- package/dist/commands/localization/glossary/suggested.d.ts +1 -0
- package/dist/commands/localization/glossary/suggested.js +20 -0
- package/dist/commands/localization/key/delete-keys.d.ts +1 -0
- package/dist/commands/localization/key/delete-keys.js +28 -0
- package/dist/commands/localization/key/delete.d.ts +1 -0
- package/dist/commands/localization/key/delete.js +24 -0
- package/dist/commands/localization/key/generate-uilm-file.d.ts +1 -0
- package/dist/commands/localization/key/generate-uilm-file.js +29 -0
- package/dist/commands/localization/key/get-by-names.d.ts +1 -0
- package/dist/commands/localization/key/get-by-names.js +24 -0
- package/dist/commands/localization/key/get-language-file-generation-history.d.ts +1 -0
- package/dist/commands/localization/key/get-language-file-generation-history.js +19 -0
- package/dist/commands/localization/key/get-localization-timeline.d.ts +1 -0
- package/dist/commands/localization/key/get-localization-timeline.js +28 -0
- package/dist/commands/localization/key/get-timeline-by-operation-id.d.ts +1 -0
- package/dist/commands/localization/key/get-timeline-by-operation-id.js +21 -0
- package/dist/commands/localization/key/get-timeline.d.ts +1 -0
- package/dist/commands/localization/key/get-timeline.js +25 -0
- package/dist/commands/localization/key/get-uilm-exported-files.d.ts +1 -0
- package/dist/commands/localization/key/get-uilm-exported-files.js +22 -0
- package/dist/commands/localization/key/get-uilm-file.d.ts +1 -0
- package/dist/commands/localization/key/get-uilm-file.js +18 -0
- package/dist/commands/localization/key/get.d.ts +1 -0
- package/dist/commands/localization/key/get.js +17 -0
- package/dist/commands/localization/key/list.d.ts +1 -0
- package/dist/commands/localization/key/list.js +39 -0
- package/dist/commands/localization/key/rollback.d.ts +1 -0
- package/dist/commands/localization/key/rollback.js +24 -0
- package/dist/commands/localization/key/save.d.ts +1 -0
- package/dist/commands/localization/key/save.js +44 -0
- package/dist/commands/localization/key/translate-all.d.ts +1 -0
- package/dist/commands/localization/key/translate-all.js +30 -0
- package/dist/commands/localization/key/translate-and-export.d.ts +7 -0
- package/dist/commands/localization/key/translate-and-export.js +132 -0
- package/dist/commands/localization/key/translate-key.d.ts +1 -0
- package/dist/commands/localization/key/translate-key.js +27 -0
- package/dist/commands/localization/key/translate-keys.d.ts +1 -0
- package/dist/commands/localization/key/translate-keys.js +31 -0
- package/dist/commands/localization/key/uilm-export.d.ts +1 -0
- package/dist/commands/localization/key/uilm-export.js +33 -0
- package/dist/commands/localization/key/uilm-import.d.ts +1 -0
- package/dist/commands/localization/key/uilm-import.js +26 -0
- package/dist/commands/localization/language/delete.d.ts +1 -0
- package/dist/commands/localization/language/delete.js +24 -0
- package/dist/commands/localization/language/list-for-tenant.d.ts +1 -0
- package/dist/commands/localization/language/list-for-tenant.js +14 -0
- package/dist/commands/localization/language/list.d.ts +1 -0
- package/dist/commands/localization/language/list.js +14 -0
- package/dist/commands/localization/language/save.d.ts +1 -0
- package/dist/commands/localization/language/save.js +36 -0
- package/dist/commands/localization/language/set-default.d.ts +1 -0
- package/dist/commands/localization/language/set-default.js +24 -0
- package/dist/commands/localization/module/list-for-tenant.d.ts +1 -0
- package/dist/commands/localization/module/list-for-tenant.js +14 -0
- package/dist/commands/localization/module/list.d.ts +1 -0
- package/dist/commands/localization/module/list.js +14 -0
- package/dist/commands/localization/module/save.d.ts +1 -0
- package/dist/commands/localization/module/save.js +32 -0
- package/dist/commands/localization/module/tag-glossary.d.ts +1 -0
- package/dist/commands/localization/module/tag-glossary.js +28 -0
- package/dist/commands/mail/config/delete.d.ts +1 -0
- package/dist/commands/mail/config/delete.js +24 -0
- package/dist/commands/mail/config/duplicate.d.ts +1 -0
- package/dist/commands/mail/config/duplicate.js +24 -0
- package/dist/commands/mail/config/get.d.ts +1 -0
- package/dist/commands/mail/config/get.js +17 -0
- package/dist/commands/mail/config/list.d.ts +1 -0
- package/dist/commands/mail/config/list.js +14 -0
- package/dist/commands/mail/config/save.d.ts +1 -0
- package/dist/commands/mail/config/save.js +44 -0
- package/dist/commands/mail/mailbox/get.d.ts +1 -0
- package/dist/commands/mail/mailbox/get.js +17 -0
- package/dist/commands/mail/mailbox/list.d.ts +1 -0
- package/dist/commands/mail/mailbox/list.js +24 -0
- package/dist/commands/mail/send.d.ts +1 -0
- package/dist/commands/mail/send.js +40 -0
- package/dist/commands/mail/sendtoany.d.ts +1 -0
- package/dist/commands/mail/sendtoany.js +41 -0
- package/dist/commands/mail/template/clone.d.ts +1 -0
- package/dist/commands/mail/template/clone.js +33 -0
- package/dist/commands/mail/template/delete.d.ts +1 -0
- package/dist/commands/mail/template/delete.js +24 -0
- package/dist/commands/mail/template/get.d.ts +1 -0
- package/dist/commands/mail/template/get.js +17 -0
- package/dist/commands/mail/template/list.d.ts +1 -0
- package/dist/commands/mail/template/list.js +24 -0
- package/dist/commands/mail/template/save.d.ts +1 -0
- package/dist/commands/mail/template/save.js +37 -0
- package/dist/commands/mfa/backup-codes/generate.d.ts +1 -0
- package/dist/commands/mfa/backup-codes/generate.js +22 -0
- package/dist/commands/mfa/backup-codes/list.d.ts +1 -0
- package/dist/commands/mfa/backup-codes/list.js +14 -0
- package/dist/commands/mfa/backup-codes/use.d.ts +1 -0
- package/dist/commands/mfa/backup-codes/use.js +18 -0
- package/dist/commands/mfa/config-get.d.ts +1 -0
- package/dist/commands/mfa/config-get.js +14 -0
- package/dist/commands/mfa/config-save.d.ts +1 -0
- package/dist/commands/mfa/config-save.js +36 -0
- package/dist/commands/mfa/disable.d.ts +1 -0
- package/dist/commands/mfa/disable.js +22 -0
- package/dist/commands/mfa/generate.d.ts +1 -0
- package/dist/commands/mfa/generate.js +22 -0
- package/dist/commands/mfa/method-set.d.ts +1 -0
- package/dist/commands/mfa/method-set.js +20 -0
- package/dist/commands/mfa/resend.d.ts +1 -0
- package/dist/commands/mfa/resend.js +20 -0
- package/dist/commands/mfa/totp-enable.d.ts +10 -0
- package/dist/commands/mfa/totp-enable.js +52 -0
- package/dist/commands/mfa/totp-setup.d.ts +1 -0
- package/dist/commands/mfa/totp-setup.js +15 -0
- package/dist/commands/mfa/totp-verify-setup.d.ts +1 -0
- package/dist/commands/mfa/totp-verify-setup.js +17 -0
- package/dist/commands/mfa/verify.d.ts +1 -0
- package/dist/commands/mfa/verify.js +26 -0
- package/dist/commands/new/web.js +115 -15
- package/dist/commands/notification/delete.d.ts +1 -0
- package/dist/commands/notification/delete.js +24 -0
- package/dist/commands/notification/get.d.ts +1 -0
- package/dist/commands/notification/get.js +17 -0
- package/dist/commands/notification/list.d.ts +1 -0
- package/dist/commands/notification/list.js +22 -0
- package/dist/commands/notification/save.d.ts +1 -0
- package/dist/commands/notification/save.js +34 -0
- package/dist/commands/notifier/list.d.ts +1 -0
- package/dist/commands/notifier/list.js +23 -0
- package/dist/commands/notifier/mark-all-read.d.ts +1 -0
- package/dist/commands/notifier/mark-all-read.js +23 -0
- package/dist/commands/notifier/mark-read.d.ts +1 -0
- package/dist/commands/notifier/mark-read.js +24 -0
- package/dist/commands/notifier/notify.d.ts +1 -0
- package/dist/commands/notifier/notify.js +39 -0
- package/dist/commands/notifier/unread.d.ts +1 -0
- package/dist/commands/notifier/unread.js +25 -0
- package/dist/commands/projects/get.js +16 -14
- package/dist/commands/projects/list.js +2 -7
- package/dist/commands/release/builds/list.js +21 -3
- package/dist/commands/release/deploy.js +121 -30
- package/dist/commands/sdk/client.d.ts +1 -0
- package/dist/commands/sdk/client.js +99 -0
- package/dist/commands/secrets/get.d.ts +1 -0
- package/dist/commands/secrets/get.js +21 -0
- package/dist/commands/secrets/save.d.ts +1 -0
- package/dist/commands/secrets/save.js +51 -0
- package/dist/commands/skill/add.d.ts +1 -0
- package/dist/commands/skill/add.js +19 -0
- package/dist/commands/skill/list.d.ts +1 -0
- package/dist/commands/skill/list.js +15 -0
- package/dist/commands/skill/show.d.ts +1 -0
- package/dist/commands/skill/show.js +15 -0
- package/dist/commands/storage/config/delete.d.ts +1 -0
- package/dist/commands/storage/config/delete.js +24 -0
- package/dist/commands/storage/config/get.d.ts +1 -0
- package/dist/commands/storage/config/get.js +17 -0
- package/dist/commands/storage/config/list.d.ts +1 -0
- package/dist/commands/storage/config/list.js +14 -0
- package/dist/commands/storage/config/save.d.ts +1 -0
- package/dist/commands/storage/config/save.js +49 -0
- package/dist/index.js +950 -152
- package/dist/lib/api.d.ts +1 -1
- package/dist/lib/api.js +39 -21
- package/dist/lib/args.d.ts +3 -0
- package/dist/lib/args.js +15 -0
- package/dist/lib/auth.d.ts +5 -2
- package/dist/lib/auth.js +23 -35
- package/dist/lib/config.js +7 -7
- package/dist/lib/json-flag.d.ts +17 -0
- package/dist/lib/json-flag.js +55 -0
- package/dist/lib/project-info.d.ts +33 -0
- package/dist/lib/project-info.js +39 -0
- package/dist/lib/prompt.d.ts +2 -0
- package/dist/lib/prompt.js +28 -0
- package/dist/lib/scaffold-web/dashboard.js +1 -1
- package/dist/lib/scaffold-web/root-files.js +1 -1
- package/dist/lib/secret-store.js +7 -7
- package/dist/lib/skills.d.ts +17 -0
- package/dist/lib/skills.js +69 -0
- package/dist/lib/token.d.ts +2 -0
- package/dist/lib/token.js +12 -0
- package/dist/lib/workspace.d.ts +0 -4
- package/dist/lib/workspace.js +1 -2
- package/dist/skills/blocks-data-gateway-configuration/SKILL.md +204 -0
- package/dist/skills/blocks-data-gateway-crud/SKILL.md +223 -0
- package/dist/skills/blocks-data-storage/SKILL.md +161 -0
- package/dist/skills/blocks-frontend-local-https/SKILL.md +100 -0
- package/dist/skills/blocks-iam-access-control/SKILL.md +49 -0
- package/dist/skills/blocks-iam-access-control/flows/feature-gating.md +38 -0
- package/dist/skills/blocks-iam-access-control/flows/manage-roles-permissions.md +109 -0
- package/dist/skills/blocks-iam-account/SKILL.md +169 -0
- package/dist/skills/blocks-iam-mfa/SKILL.md +124 -0
- package/dist/skills/blocks-iam-organizations/SKILL.md +43 -0
- package/dist/skills/blocks-iam-organizations/flows/admin-mutations.md +89 -0
- package/dist/skills/blocks-iam-organizations/flows/read-and-switch.md +57 -0
- package/dist/skills/blocks-iam-sso-oidc-configuration/SKILL.md +89 -0
- package/dist/skills/blocks-iam-sso-oidc-implementation/SKILL.md +80 -0
- package/dist/skills/blocks-iam-users/SKILL.md +131 -0
- package/dist/skills/blocks-localization-configuration/SKILL.md +149 -0
- package/dist/skills/blocks-localization-implementation/SKILL.md +63 -0
- package/dist/skills/blocks-mail/SKILL.md +95 -0
- package/dist/skills/blocks-notification/SKILL.md +69 -0
- package/dist/skills/blocks-notifier/SKILL.md +107 -0
- package/dist/skills/blocks-onboarding/SKILL.md +78 -0
- package/dist/skills/blocks-release-deployment/SKILL.md +81 -0
- package/dist/skills/blocks-secrets/SKILL.md +81 -0
- package/dist/skills/blocks-storage-configuration/SKILL.md +93 -0
- package/dist/skills/lint.mjs +168 -0
- package/package.json +4 -4
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: blocks-data-storage
|
|
3
|
+
description: "Store and serve files on a SELISE Blocks project: presigned/local-storage upload, download, folder browsing, tags/metadata, and delete, via the blocks CLI ('data files *') for admin/scripting or the @seliseblocks/client SDK ('data.files'/'data.dms') for in-app upload/download flows. Use for prompts like upload a file and get a download link, attach an image to a record, create a folder, let users download a file, tag or delete an uploaded file. Separate from the data model — schemas/records live in blocks-data-gateway-configuration/-crud; this covers files/DMS only, implementation-mode, SDK-driven."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Blocks Data — Storage (Files / DMS)
|
|
7
|
+
|
|
8
|
+
Storage is DMS (document management system). Two ways to reach it, pick based on what the user is actually doing:
|
|
9
|
+
|
|
10
|
+
- **`blocks data files *` (CLI)** — admin tasks, one-off scripts, or anything the user is doing from a terminal/agent context rather than inside a running app.
|
|
11
|
+
- **`@seliseblocks/client`'s `data.files` / `data.dms` namespaces (SDK)** — wiring upload/download/browse into actual app code (a React component, a form submit handler).
|
|
12
|
+
|
|
13
|
+
Both surfaces do the same work; which one to use is about *where the code runs*, not a capability gap — unlike some other Data resources, this one has full CLI coverage.
|
|
14
|
+
|
|
15
|
+
**Prerequisite:** a project is selected (`blocks use <tenantId>`). For the SDK path, a frontend also needs to be scaffolded. If login/project state is unknown, or there's no app to write SDK code into yet, run the blocks-onboarding skill first — it gets `blocks new web` scaffolding in place (React 18 + TypeScript + Vite + Tailwind + Radix + TanStack Query + a single `@seliseblocks/client` instance). The SDK examples below assume that scaffold's shared client, conventionally exported as `blocksClient` from `src/lib/blocks/client.ts`.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { blocksClient } from "../lib/blocks/client";
|
|
19
|
+
const { files, dms } = blocksClient.data;
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Store a file here and keep its returned `fileId` in a schema field (see the blocks-data-gateway-crud skill) to associate it with a record.
|
|
23
|
+
|
|
24
|
+
## CLI quick reference
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Cloud storage (pre-signed URL), two steps
|
|
28
|
+
blocks data files presigned-upload-url --name invoice.pdf --access-modifier Public --json
|
|
29
|
+
blocks data files upload-to-url --url "<uploadUrl from above>" --file ./invoice.pdf --content-type application/pdf --yes --json
|
|
30
|
+
|
|
31
|
+
# Local storage, one step
|
|
32
|
+
blocks data files upload-to-local-storage --file ./invoice.pdf --access-modifier Public --yes --json
|
|
33
|
+
|
|
34
|
+
# Register the uploaded file in a DMS folder (upload alone doesn't do this)
|
|
35
|
+
blocks data files dms-upload --file-storage-id <fileId> --artifact-name invoice.pdf --yes --json
|
|
36
|
+
|
|
37
|
+
# Read it back
|
|
38
|
+
blocks data files dms-list --parent-id "" --json
|
|
39
|
+
blocks data files get <fileId> --json
|
|
40
|
+
|
|
41
|
+
# Folders, metadata, cleanup
|
|
42
|
+
blocks data files create-folder Invoices --yes --json
|
|
43
|
+
blocks data files update-additional-info <fileId> --additional-properties '{"status":"reviewed"}' --yes --json
|
|
44
|
+
blocks data files delete <fileId> --yes --json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Same two upload paths as the SDK section below (pick based on the project's storage backend, not per-call), same `--dry-run`-before-`--yes` discipline as every other `blocks` mutation.
|
|
48
|
+
|
|
49
|
+
**Shortcut:** `blocks data files upload --file ./invoice.pdf --yes --json` composes the manual sequence above into one command — presign + PUT + `dms.uploadFiles` registration for cloud storage, or add `--local-storage` for the one-step local-storage path (uploads only, no DMS registration in that case). Same relationship as `data sync` is to the manual schema/rules/reload sequence elsewhere in this skill pack: reach for the manual steps when you need to inspect or reuse an intermediate result (e.g. the presigned URL itself), reach for `upload` when you just want the file stored.
|
|
50
|
+
|
|
51
|
+
## Two upload paths — pick one per deployment
|
|
52
|
+
|
|
53
|
+
A project's storage is backed by either cloud object storage (Azure Blob, S3, etc.) or local storage on the Blocks Data host. Which one applies is a property of the project's storage configuration, not something the frontend chooses per call — but the SDK exposes a distinct method for each:
|
|
54
|
+
|
|
55
|
+
| Deployment | Call sequence |
|
|
56
|
+
|---|---|
|
|
57
|
+
| **Cloud storage** (pre-signed URL) | `files.presignedUploadUrl(...)` → `files.uploadToUrl(...)` |
|
|
58
|
+
| **Local storage** | `files.uploadToLocalStorage(...)` (one call, no presign step) |
|
|
59
|
+
|
|
60
|
+
Both are followed by the same registration step, `dms.uploadFiles(...)`, if the file needs to show up in a DMS folder.
|
|
61
|
+
|
|
62
|
+
**Where that configuration lives:** `blocks storage config get/list/save/delete` (a separate top-level command group, not `data files`) reads/writes the named storage configuration itself — host, port, credentials, region/endpoint or connection string, and strategy — i.e. which provider a given `configurationName` points at, cloud or local. This skill only covers *using* that config name when uploading; managing the config's own fields is out of scope here — see the blocks-storage-configuration skill.
|
|
63
|
+
|
|
64
|
+
## Step 1a (cloud) — get a pre-signed upload URL
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const presign = await files.presignedUploadUrl({
|
|
68
|
+
name: "invoice.pdf",
|
|
69
|
+
contentType: "application/pdf",
|
|
70
|
+
configurationName: "Default", // example only — confirm the storage config name for this project
|
|
71
|
+
moduleName: 3, // example only — confirm the module value expected by this project
|
|
72
|
+
parentDirectoryId: "", // required — "" for root, or a folder id; never omit/null
|
|
73
|
+
accessModifier: "Public" // "Public" (readable without auth) or "Private"
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
It returns the pre-signed `uploadUrl` plus a `fileId` you'll need for the next steps — the method's return type is `Promise<unknown>`, so read the exact response shape at runtime rather than assuming a typed contract. Note `contentType` in this request is not forwarded to the presign call itself (the normalizer drops it); pass it again to `uploadToUrl` below so the PUT gets the right `Content-Type` header. Treat `configurationName` and `moduleName` values as project-specific unless the tenant's storage configuration says otherwise.
|
|
78
|
+
|
|
79
|
+
## Step 1b (cloud) — PUT the binary to that URL
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
await files.uploadToUrl({
|
|
83
|
+
url: presign.uploadUrl,
|
|
84
|
+
body: fileBlob, // Blob | ArrayBuffer | ArrayBufferView | ReadableStream
|
|
85
|
+
contentType: "application/pdf"
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This is the one call in the whole skill that is **provider-direct, not a Blocks API call** — it sends **no `x-blocks-key` and no bearer token**. It PUTs straight to the storage provider's pre-signed URL. If you don't set your own `x-ms-blob-type` header, the SDK adds `x-ms-blob-type: Blockblob` for you (Azure's block-blob upload header); verify that this matches the storage provider and signed-URL policy for the project rather than assuming every provider ignores extra headers.
|
|
90
|
+
|
|
91
|
+
## Step 1 (local storage) — the one-call alternative
|
|
92
|
+
|
|
93
|
+
For local-storage-backed deployments, skip the presign/PUT pair entirely and upload straight through Blocks Data:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
await files.uploadToLocalStorage({
|
|
97
|
+
name: "invoice.pdf",
|
|
98
|
+
file: fileBlob, // Blob | File
|
|
99
|
+
configurationName: "Default",
|
|
100
|
+
parentDirectoryId: "",
|
|
101
|
+
accessModifier: "Public",
|
|
102
|
+
tags: ["invoice", "2026"]
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The SDK builds a multipart `FormData` body for you (`File`, `Name`, `ItemId`, `MetaData`, `ParentDirectoryId`, `Tags`, `AccessModifier`, `ConfigurationName`, `AdditionalProperties[key]`) and sends it as a normal authenticated Blocks API call (`x-blocks-key` + bearer, unlike the pre-signed PUT above).
|
|
107
|
+
|
|
108
|
+
## Step 2 — register the file in a DMS folder
|
|
109
|
+
|
|
110
|
+
Neither upload path above makes a file appear in a document folder by itself — that's a separate registration call:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
await dms.uploadFiles({
|
|
114
|
+
upload: [{
|
|
115
|
+
fileStorageId: presign.fileId, // the fileId from presignedUploadUrl (or the equivalent id from uploadToLocalStorage's response)
|
|
116
|
+
artifactName: "invoice.pdf",
|
|
117
|
+
parentId: "", // "" for root, or a folder id
|
|
118
|
+
tags: ["invoice"]
|
|
119
|
+
}]
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Despite the method's name suggesting a binary upload, this is the DMS *registration* call — the bytes are already stored by Step 1a/1b or Step 1. `upload` is an array, so multiple files can be registered into folders in one call.
|
|
124
|
+
|
|
125
|
+
## Step 3 — read it back
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const folder = await dms.list({ parentId: "", take: 20 });
|
|
129
|
+
const meta = await files.get(presign.fileId, { configurationName: "Default" });
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`dms.list` returns the combined folder+file listing for a `parentId` (`""` = root), with `searchKey`/`skip`/`take` for search and paging. The same endpoint is also reachable as `files.listFolder(...)` — they're identical calls, `dms.list` is the more discoverable name for folder-browsing UI. `files.get` confirms a specific upload landed: a successful response with a non-null `url` (download link) and matching `name`/size means the file is stored.
|
|
133
|
+
|
|
134
|
+
## Other file operations
|
|
135
|
+
|
|
136
|
+
- **`files.getMany({ fileIds, configurationName })`** — batch read instead of one `files.get` per attachment.
|
|
137
|
+
- **`files.info({ page, pageSize, sort, filter })`** — paged file metadata/listing for storage-browser UIs; unlike `presignedUploadUrl`, the SDK does not remap these field names to PascalCase — pass exactly what your app builds.
|
|
138
|
+
- **`files.updateAdditionalInfo({ itemId, additionalProperties })`** — attach searchable metadata to an uploaded file, e.g. a business reference or workflow status.
|
|
139
|
+
- **`files.delete({ fileId, configurationName?, eventQueueName? })`** — delete a file.
|
|
140
|
+
- **`dms.createFolder({ artifactName, parentId?, configurationName? })`** / **`dms.deleteFolder({ folderId, configurationName? })`** — DMS folder management.
|
|
141
|
+
|
|
142
|
+
## Gotchas
|
|
143
|
+
|
|
144
|
+
- **Terminal/admin task → CLI (`data files *`); app code → SDK.** Both exist and both are fully supported; don't default to writing a throwaway script against the SDK for something the CLI already does in one command, and don't reach for `blocks` from inside a React component.
|
|
145
|
+
- **`--module-name` / `moduleName` and `--parent-directory-id` / `parentDirectoryId` on the presigned-upload-url call** — optional in the CLI/SDK types, but the underlying endpoint may require them for a given project/storage setup. Confirm the expected module value with the project's storage configuration, and always send a `parentDirectoryId` value (`""` for root) when the endpoint requires a parent folder value — the CLI command defaults it to `""` automatically if you omit `--parent-directory-id`.
|
|
146
|
+
- **The pre-signed PUT is the one call with no Blocks auth.** `uploadToUrl` sends no `x-blocks-key` and no bearer token by design — everything else in this skill (`presignedUploadUrl`, `uploadToLocalStorage`, `dms.*`, `files.get`/`getMany`/`info`/`delete`) is a normal authenticated Blocks API call.
|
|
147
|
+
- **Upload ≠ visible in a folder.** `uploadToUrl`/`uploadToLocalStorage` only gets the bytes stored; call `dms.uploadFiles` afterward if the file needs to appear under a DMS folder.
|
|
148
|
+
- **Most file/DMS methods return `Promise<unknown>`.** The SDK doesn't hand you a typed response for this surface — check the actual JSON shape at runtime (e.g. log the presign response once) rather than assuming field names beyond what's documented here.
|
|
149
|
+
- **`accessModifier`** is `"Public"` (readable without auth) or `"Private"` — decide per file, not per project.
|
|
150
|
+
- Don't confuse this with the data model: a file's `fileId` is just a string you store in a schema field via **blocks-data-gateway-crud**; this skill never touches schemas.
|
|
151
|
+
|
|
152
|
+
## Example trigger prompts
|
|
153
|
+
|
|
154
|
+
- "Upload a PDF and get a download link." → CLI (`data files presigned-upload-url` + `upload-to-url`, or `upload-to-local-storage`) for a one-off; SDK if it's a feature in the app.
|
|
155
|
+
- "Attach an image to this record." (upload via CLI or SDK, then store the `fileId` via blocks-data-gateway-crud)
|
|
156
|
+
- "Let users download this file from the app." → SDK, this is in-app behavior.
|
|
157
|
+
- "Create a folder and list its contents." → `data files create-folder` + `data files dms-list`.
|
|
158
|
+
- "Get a presigned upload URL for a cloud storage upload." → `data files presigned-upload-url`.
|
|
159
|
+
- "This deployment uses local storage — how do I upload a file?" → `data files upload-to-local-storage`.
|
|
160
|
+
- "Tag this uploaded file with a status so it's searchable later." → `data files update-additional-info`.
|
|
161
|
+
- "Delete this file / delete this folder." → `data files delete` / `data files delete-folder`.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: blocks-frontend-local-https
|
|
3
|
+
description: "Run a scaffolded (`blocks new web`) Blocks app locally over HTTPS on its real project domain — required for hosted IAM login, since plain HTTP or localhost never gets the session cookie. The scaffold already automates cert generation (npm run cert, no OpenSSL needed) and HTTPS serving via vite.config.ts. Covers running that flow, trusting the cert, the hosts-file entry, and troubleshooting. Use when running a scaffolded app over HTTPS, hitting 'SSO cookie not set' / Vite 'Blocked request' errors, trusting the dev cert, or asking why local login redirects back but doesn't stay signed in."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Blocks Frontend — Local HTTPS for a Scaffolded App
|
|
7
|
+
|
|
8
|
+
This is the local dev loop for an app already created with `blocks new web` (see the blocks-onboarding skill for the scaffold command itself — this skill doesn't repeat it). The scaffold **already generates its own cert tooling**; nothing here is built from scratch, and nothing uses raw `openssl`/`curl`/`fetch`.
|
|
9
|
+
|
|
10
|
+
## Why localhost doesn't work
|
|
11
|
+
|
|
12
|
+
Browser login goes through the hosted Blocks IAM IdP flow (`blocksClient.auth.idp.redirectToProvider()` / `.callback()`), which finishes by IAM setting a **Secure, domain-scoped session cookie**. Browsers won't store or send that cookie on plain `http://localhost` — it has to be HTTPS, and it has to be on the project's real domain, or the cookie silently never lands and the app looks "logged in" for a second then bounces back to logged-out.
|
|
13
|
+
|
|
14
|
+
## Where the domain comes from
|
|
15
|
+
|
|
16
|
+
`--app-domain` on `blocks new web` is the app's real Blocks origin, e.g. `https://dbpdba.seliseblocks.com`. The generated `.env` keeps two derived values:
|
|
17
|
+
|
|
18
|
+
- `VITE_BLOCKS_APP_DOMAIN` — the full value as passed, with scheme (`https://dbpdba.seliseblocks.com`).
|
|
19
|
+
- `VITE_BLOCKS_DEV_HOST` — the same host with no scheme (`dbpdba.seliseblocks.com`), computed by the scaffold generator and used everywhere locally: hosts file, cert `commonName`/SAN, and `vite.config.ts`'s `server.host`/`allowedHosts`.
|
|
20
|
+
|
|
21
|
+
You never need to look this up separately — it's already sitting in `.env` after scaffolding.
|
|
22
|
+
|
|
23
|
+
## The flow
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
cd <appName>
|
|
27
|
+
npm install
|
|
28
|
+
npm run cert
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`npm run cert` runs `scripts/generate-cert.mjs`, which reads `VITE_BLOCKS_DEV_HOST` from `.env` (or `process.env`, or an explicit `npm run cert -- <domain>` argument) and uses the `selfsigned` npm dependency to write `.cert/dev-key.pem` and `.cert/dev-cert.pem`, with `subjectAltName` covering the domain, `localhost`, and `127.0.0.1`. This is pure Node — it works from a plain PowerShell prompt with no OpenSSL and no Git Bash/WSL switch.
|
|
32
|
+
|
|
33
|
+
Next, map the domain to your machine — add one line to the hosts file (needs admin/elevated):
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
127.0.0.1 dbpdba.seliseblocks.com
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Windows path: `C:\Windows\System32\drivers\etc\hosts` (edit as Administrator).
|
|
40
|
+
|
|
41
|
+
Then:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run dev
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`vite.config.ts` picks up `.cert/dev-key.pem` + `.cert/dev-cert.pem` automatically when both exist and serves HTTPS on `VITE_BLOCKS_DEV_HOST`:`VITE_BLOCKS_DEV_PORT` (default port `5173`, `strictPort: true` because the port is baked into the registered OIDC redirect URI). It also sets `allowedHosts` to that domain, working around Vite's default DNS-rebinding protection which otherwise 404s custom hosts with "Blocked request."
|
|
48
|
+
|
|
49
|
+
Finally, open the app at:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
https://dbpdba.seliseblocks.com:5173
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Not** `http://`, **not** `localhost` — either one skips the cookie entirely even though the app loads.
|
|
56
|
+
|
|
57
|
+
## Trusting the cert (optional but recommended)
|
|
58
|
+
|
|
59
|
+
The cert is self-signed, so the browser shows a one-time warning until trusted. `npm run cert` prints the exact trust command for your OS when it finishes:
|
|
60
|
+
|
|
61
|
+
- Windows (elevated prompt): `certutil -addstore -f Root .cert\dev-cert.pem`
|
|
62
|
+
- macOS: `sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain .cert/dev-cert.pem`
|
|
63
|
+
- Linux: `sudo cp .cert/dev-cert.pem /usr/local/share/ca-certificates/blocks-dev.crt && sudo update-ca-certificates`
|
|
64
|
+
|
|
65
|
+
Restart the browser after trusting so it picks up the new trust store entry. `.cert/` is already gitignored by the scaffold — it's per-machine, never committed.
|
|
66
|
+
|
|
67
|
+
## Still need a public OIDC client
|
|
68
|
+
|
|
69
|
+
Local HTTPS alone doesn't make login succeed if no OIDC client is registered yet, or if its `redirect_uris` don't include this exact dev origin. That registration is portal-only (see blocks-onboarding's Gotchas) — out of scope here, but it's the next thing to check if HTTPS is right and login still fails. The redirect URI must match byte-for-byte, including `:5173`.
|
|
70
|
+
|
|
71
|
+
## Gotchas
|
|
72
|
+
|
|
73
|
+
**Custom app domain: the API base URL must share its registrable domain, or the cookie never lands.** `blocks new web --app-domain` isn't limited to `*.seliseblocks.com` — it also supports custom domains (e.g. `abc.slsblx.com`, `xyz.blx10.com`). On a custom domain, the hosted-login session cookie is only stored by the browser if `VITE_BLOCKS_API_URL` shares the app's registrable domain. Concretely:
|
|
74
|
+
|
|
75
|
+
- `abc.slsblx.com` → `VITE_BLOCKS_API_URL` must be `https://blocksapi.slsblx.com`
|
|
76
|
+
- `xyz.blx10.com` → `VITE_BLOCKS_API_URL` must be `https://blocksapi.blx10.com`
|
|
77
|
+
|
|
78
|
+
If `VITE_BLOCKS_API_URL` is left at the default `https://api.seliseblocks.com` while the app itself runs on a custom domain, the browser treats the API as cross-site relative to the app and never stores the cookie — login still redirects back and *looks* successful, but cookie-based calls (`/iam/me`, organization switching, logout) silently fail. Check `VITE_BLOCKS_API_URL` in `.env` first whenever the app domain is not `*.seliseblocks.com` and auth-dependent calls are failing despite HTTPS and the cert being set up correctly.
|
|
79
|
+
|
|
80
|
+
## Troubleshooting
|
|
81
|
+
|
|
82
|
+
| Symptom | Likely cause | Fix |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| Login redirects back but app shows logged-out | Opened on `http://` or `localhost` instead of the HTTPS dev host | Check the URL bar: must be `https://<VITE_BLOCKS_DEV_HOST>:5173` exactly |
|
|
85
|
+
| Browser "not private" warning | Self-signed cert not trusted yet | Run the OS trust command `npm run cert` printed, then restart the browser |
|
|
86
|
+
| Vite: "Blocked request. This host is not allowed" | `allowedHosts` doesn't include the host being requested — usually `.env`'s `VITE_BLOCKS_DEV_HOST` was edited/missing after scaffold, or the browser is hitting a different hostname than expected | Confirm `.env` has the right `VITE_BLOCKS_DEV_HOST` and that the URL bar matches it exactly |
|
|
87
|
+
| Page doesn't load at all / DNS error | Hosts file entry missing or wrong | Add `127.0.0.1 <VITE_BLOCKS_DEV_HOST>` to `C:\Windows\System32\drivers\etc\hosts` (as Administrator) |
|
|
88
|
+
| `npm run cert` errors "No domain given" | `.env` missing or `VITE_BLOCKS_DEV_HOST` not set | Confirm `.env` exists with `VITE_BLOCKS_DEV_HOST=<host>`, or run `npm run cert -- <domain>` explicitly |
|
|
89
|
+
| `npm run dev` fails to bind the port | Port 5173 already in use (dev server uses `strictPort`, won't fall back) | Free port 5173, or the port is fixed because it's part of the registered OIDC redirect URI — don't just change it without updating the OIDC client too |
|
|
90
|
+
| HTTPS works, cert trusted, login still fails | No OIDC client registered yet, or its redirect URI doesn't match this origin exactly | Register/update the public OIDC client in the portal with `https://<VITE_BLOCKS_DEV_HOST>:5173/login/callback` as a redirect URI (portal-only, see blocks-onboarding) |
|
|
91
|
+
| Works for one dev, fails for a teammate | Each machine needs its own cert + hosts entry — `.cert/` is gitignored on purpose | Teammate runs `npm run cert` and adds the hosts entry on their own machine |
|
|
92
|
+
|
|
93
|
+
## Example trigger prompts
|
|
94
|
+
|
|
95
|
+
- "Run my app locally over HTTPS on its real domain so SSO works"
|
|
96
|
+
- "My local login isn't working — it just bounces back to the login page"
|
|
97
|
+
- "How do I set up the dev cert for this scaffolded app?"
|
|
98
|
+
- "I'm getting 'Blocked request. This host is not allowed' from Vite"
|
|
99
|
+
- "Do I need OpenSSL to run npm run cert on Windows?"
|
|
100
|
+
- "Why does login work in production but not on localhost?"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: blocks-iam-access-control
|
|
3
|
+
description: "Work with SELISE Blocks RBAC (roles & permissions) via `blocks iam roles/permissions *` (CLI, project-scoped) or `blocksClient.iam.*` (SDK), never raw fetch/curl. Two facets: read-only feature-gating by the current user's own roles/permissions (common, safe) vs. creating/editing role and permission definitions (sensitive, human-confirmed only — CLI `--dry-run`→`--yes` or an in-app admin screen). OIDC/identity-provider provisioning stays portal-only, a different concern. Use for permission-gated UI, role/permission pickers, or building/scripting role & permission admin ('gate this button by permission', 'create a role and grant permissions', 'list permissions by severity')."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Blocks IAM — Access Control (Permissions & Roles)
|
|
7
|
+
|
|
8
|
+
This skill covers **permission and role definitions** in SELISE Blocks — the RBAC model itself, not who has which role (that's the blocks-iam-users skill). Everything goes through either `blocks iam roles/permissions *` (CLI) or `blocksClient.iam.*` from **`@seliseblocks/client`**, the single SDK instance every `blocks new web` scaffold wires up at `src/lib/blocks/client.ts` and exports as `blocksClient`. No raw `fetch`/`curl` for either surface.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { blocksClient } from "../../lib/blocks/client";
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## The platform boundary — read this before writing any code
|
|
15
|
+
|
|
16
|
+
Role and permission administration is **not** portal-only or app-UI-only — `blocks` has a full, working CLI surface for it too. There are two equally real surfaces for the same operations, and the choice is about *where the human is*, not which one is "allowed" — see [flows/manage-roles-permissions.md](flows/manage-roles-permissions.md) for the full command reference and the CLI-vs-SDK decision.
|
|
17
|
+
|
|
18
|
+
Identity-provider/OIDC client provisioning is the one piece that really is **portal-only, human-driven**, at `https://os.seliseblocks.com` — unrelated to roles/permissions, don't bolt it onto this skill.
|
|
19
|
+
|
|
20
|
+
Keep the two facets below (read-only feature-gating vs. sensitive admin mutations) separate in your head (and in your code) — they have very different risk profiles regardless of which surface (CLI or SDK) you're using.
|
|
21
|
+
|
|
22
|
+
## Facet 1 — Feature-gating a frontend by the user's own permissions (common, low risk)
|
|
23
|
+
|
|
24
|
+
Read-only, scoped to whoever is signed in, needs no special confirmation. `useCurrentUser()` + `iam.resources.features()` + `iam.roles.assignable()`.
|
|
25
|
+
|
|
26
|
+
→ Full walkthrough: [flows/feature-gating.md](flows/feature-gating.md)
|
|
27
|
+
|
|
28
|
+
## Facet 2 — Creating/editing roles & permissions (sensitive)
|
|
29
|
+
|
|
30
|
+
Legitimate only in direct response to a human's explicit, in-the-moment instruction — CLI (`--dry-run` reviewed, then `--yes`) or a signed-in admin's own in-app screen. Never something an agent decides to invoke on its own initiative.
|
|
31
|
+
|
|
32
|
+
→ Full command reference, SDK methods, and confirm-before-mutating pattern: [flows/manage-roles-permissions.md](flows/manage-roles-permissions.md)
|
|
33
|
+
|
|
34
|
+
## Gotchas
|
|
35
|
+
|
|
36
|
+
- **CLI mutations are project-scoped, not account-scoped** — they run against the impersonated-project token; `blocks iam me` is the one IAM command that uses the account token instead.
|
|
37
|
+
- **Role hierarchy and permission assignment key off `slug`**, not `itemId`.
|
|
38
|
+
- **Never fire a create/update/assign-permissions call — CLI or SDK — without a human confirming that specific change first.** See [flows/manage-roles-permissions.md](flows/manage-roles-permissions.md) for the full discipline.
|
|
39
|
+
- **OIDC/identity-provider client provisioning is always portal-only**, independent of everything above.
|
|
40
|
+
|
|
41
|
+
## Example trigger prompts
|
|
42
|
+
|
|
43
|
+
- "Only show the delete button to users who have the `order::delete` permission." → Facet 1
|
|
44
|
+
- "Hide this whole admin section unless the signed-in user has an admin role." → Facet 1
|
|
45
|
+
- "What roles am I allowed to assign to other users?" → Facet 1
|
|
46
|
+
- "Show me permissions grouped by severity in a settings panel." → Facet 1
|
|
47
|
+
- "Build an admin page where I can create a role and pick which permissions it gets." → Facet 2
|
|
48
|
+
- "Create a `content-editor` role from the CLI with these permissions." → Facet 2
|
|
49
|
+
- "Can you just set up a few default roles for my project?" → confirm the exact list with the human first (in chat, or via a reviewed `--dry-run`), then run each `blocks iam roles create`/`assign-permissions` with `--yes` only after they say go — don't auto-provision without that per-change confirmation.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Flow: Feature-gating a frontend by the user's own permissions (common, low risk)
|
|
2
|
+
|
|
3
|
+
This is read-only against IAM and scoped to whoever is signed in, so it needs no special confirmation — build it the same way you'd build any other data-fetching feature.
|
|
4
|
+
|
|
5
|
+
The scaffold already gives you a `useCurrentUser()` hook (`src/features/profile/useCurrentUser.ts`) wrapping `blocksClient.iam.me()` with TanStack Query; `me()` returns `{ data: { itemId, email, firstName, lastName, roles: string[], permissions: string[], ... } }`. Reuse it instead of re-fetching:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// src/features/access/usePermission.ts
|
|
9
|
+
import { useCurrentUser } from "../profile/useCurrentUser";
|
|
10
|
+
|
|
11
|
+
export function useHasPermission(permission: string): boolean {
|
|
12
|
+
const me = useCurrentUser();
|
|
13
|
+
return me.data?.data?.permissions?.includes(permission) ?? false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function useHasRole(role: string): boolean {
|
|
17
|
+
const me = useCurrentUser();
|
|
18
|
+
return me.data?.data?.roles?.includes(role) ?? false;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
// src/shared/ui/RequirePermission.tsx
|
|
24
|
+
import type { ReactNode } from "react";
|
|
25
|
+
import { useHasPermission } from "../../features/access/usePermission";
|
|
26
|
+
|
|
27
|
+
export function RequirePermission({ permission, children }: { permission: string; children: ReactNode }) {
|
|
28
|
+
if (!useHasPermission(permission)) return null;
|
|
29
|
+
return <>{children}</>;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Two more read methods round this out:
|
|
34
|
+
|
|
35
|
+
- `blocksClient.iam.resources.features(query?)` — feature/resource flags for the active user context; use this to drive nav items or feature flags that are more granular than a flat permission string.
|
|
36
|
+
- `blocksClient.iam.roles.assignable()` — lists roles the **current caller** is allowed to assign. If you're building a "grant this user a role" picker, populate it from `assignable()`, not from `roles.list()` — don't assume every role in the system is one this particular admin may hand out.
|
|
37
|
+
|
|
38
|
+
There is also a CLI read path for the same data, useful outside an app (scripting/inspection): `blocks iam roles list/get/assignable` and `blocks iam permissions list/get/by-severity` — see [manage-roles-permissions.md](manage-roles-permissions.md) for the full CLI command reference (it covers both reads and mutations).
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Flow: Creating/editing roles & permissions (sensitive)
|
|
2
|
+
|
|
3
|
+
This is the write side, and it's legitimate **only in direct response to a human's explicit, in-the-moment instruction** — either that human running `blocks iam roles/permissions create|update|assign-permissions` themselves (with a `--dry-run` reviewed first), or a signed-in admin operating their own in-app admin screen. Never something an agent decides to invoke on its own initiative.
|
|
4
|
+
|
|
5
|
+
## CLI command reference
|
|
6
|
+
|
|
7
|
+
All project-scoped — every command resolves the active project (`blocks use <tenantId>` or an explicit `--project <tenantId>`) and runs on an impersonated project token, not the account token `iam me` uses.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
blocks iam roles list [--page] [--page-size] [--search] [--slugs a,b] [--organization-id] [--filter '<json>'] [--json]
|
|
11
|
+
blocks iam roles get <id> [--json]
|
|
12
|
+
blocks iam roles create --name <n> [--slug] [--description] [--parent-role-slug] [--can-create-own] [--body '<json>'|--file <path>] [--dry-run] [--yes] [--json]
|
|
13
|
+
blocks iam roles update <itemId> [--name] [--description] [--parent-role-slug] [--propagate-to-other-org] [--can-create-own] [--body '<json>'|--file <path>] [--dry-run] [--yes] [--json]
|
|
14
|
+
blocks iam roles assign-permissions <slug> [--add-permissions a,b] [--remove-permissions a,b] [--organization-id] [--dry-run] [--yes] [--json]
|
|
15
|
+
blocks iam roles assignable [--json]
|
|
16
|
+
|
|
17
|
+
blocks iam permissions list [--page] [--page-size] [--search] [--type <0-3>] [--severity <0-4>] [--resource-group] [--tags a,b] [--resources a,b] [--is-built-in] [--is-archived] [--roles a,b] [--organization-id] [--filter '<json>'] [--json]
|
|
18
|
+
blocks iam permissions get <id> [--json]
|
|
19
|
+
blocks iam permissions create --name <n> [--type] [--description] [--resource] [--resource-group] [--tags a,b] [--severity] [--is-built-in] [--dependent-permissions a,b] [--body '<json>'|--file <path>] [--dry-run] [--yes] [--json]
|
|
20
|
+
blocks iam permissions update <id> [same flags as create, plus --is-archived] [--dry-run] [--yes] [--json]
|
|
21
|
+
blocks iam permissions by-severity [--json]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Mutating commands (`create`, `update`, `assign-permissions`) follow the same discipline as every other mutating command in this CLI: pass `--dry-run` first to see the exact request body and endpoint with no network call, then re-run with `--yes` (or you'll be prompted to confirm) to actually send it.
|
|
25
|
+
|
|
26
|
+
## Two equally real surfaces
|
|
27
|
+
|
|
28
|
+
The choice is about *where the human is*, not which one is "allowed":
|
|
29
|
+
|
|
30
|
+
- **`blocks iam roles/permissions *` from a terminal** — a human (or an agent acting on that human's explicit, in-the-moment instruction) runs the CLI directly. `--dry-run` is the CLI's own review step; treat a clean dry-run plus the human's go-ahead as the confirmation, then run with `--yes`.
|
|
31
|
+
- **`blocksClient.iam.roles`/`iam.permissions` from inside an app** — for building an admin settings screen. If you're building that user their own admin screen, and *they* click "Create role" through that screen, calling `iam.roles.create()` from the app's code is exactly what the SDK method is for.
|
|
32
|
+
|
|
33
|
+
The actual line is not "CLI vs SDK" — it's:
|
|
34
|
+
|
|
35
|
+
- **Fine:** a command run because a human just asked for this specific change (terminal or in-app), bounded by that human's own IAM permissions.
|
|
36
|
+
- **Not fine:** an agent deciding on its own to call `create`/`update`/`assignPermissions` (CLI or SDK) — whether to "help out," to fix something it noticed, or as part of a larger task the user didn't ask it to take this specific action for.
|
|
37
|
+
|
|
38
|
+
## SDK methods (write side)
|
|
39
|
+
|
|
40
|
+
All from `blocksClient.iam`, per `iam-client.ts`:
|
|
41
|
+
|
|
42
|
+
- `permissions.create(request)` / `permissions.update(id, request)` — define or edit a permission.
|
|
43
|
+
- `permissions.list(request)` — paged/filtered search.
|
|
44
|
+
- `permissions.bySeverity()` — permissions grouped by severity, handy for a categorized picker.
|
|
45
|
+
- `permissions.get(id)` — one permission's detail.
|
|
46
|
+
- `roles.create(request)` / `roles.update(request)` — define or edit a role.
|
|
47
|
+
- `roles.list(request)` / `roles.get(id)` — search / fetch one role.
|
|
48
|
+
- `roles.assignPermissions(request)` — attach/detach permissions on a role.
|
|
49
|
+
- `roles.assignable()` — same read method as feature-gating; also useful here to limit which roles this admin's screen lets them touch at all.
|
|
50
|
+
- `resources.groups()` — metadata for grouping permissions by resource in the UI (e.g. a permissions picker organized by resource/module).
|
|
51
|
+
|
|
52
|
+
The SDK deliberately leaves these request bodies as open `Record<string, unknown>` rather than locking you to a fixed shape — confirm exact field names against the portal or a `list()`/`get()` response before hardcoding new ones. Two fields the SDK's own types do pin down: a role's `slug` (`BlocksRole.slug`) is its stable key — use it, not `itemId`, anywhere the API expects a role reference (e.g. `assignPermissions`); a permission's `resource` and `roles[]` (`BlocksPermission`) tell you what it's scoped to and which roles already hold it.
|
|
53
|
+
|
|
54
|
+
## Confirm before mutating
|
|
55
|
+
|
|
56
|
+
**Before calling any of `permissions.create`, `permissions.update`, `roles.create`, `roles.update`, or `roles.assignPermissions` from your admin screen's code, the screen itself must get an explicit, in-the-moment confirmation from the admin operating it** — mirror the discipline `blocks iam roles/permissions create|update|assign-permissions` enforces natively with `--dry-run` before `--yes`. Concretely, that means the screen should:
|
|
57
|
+
|
|
58
|
+
1. Let the admin build up the change in the UI (pick a role, check/uncheck permissions, edit a name) without calling anything yet.
|
|
59
|
+
2. Show a clear summary of exactly what will change — "Grant `Editor` role: + `content::publish`, − `content::archive`" — before any network call.
|
|
60
|
+
3. Only fire the `create`/`update`/`assignPermissions` call after the admin clicks an explicit confirm ("Save changes", "Create role") for *that specific* change.
|
|
61
|
+
|
|
62
|
+
Don't collapse steps 2–3 into an auto-save on every checkbox click, and don't have an agent call these methods proactively (e.g. as part of "let me clean up your roles" or "I'll just add the permission you mentioned needing") — only in direct response to the human's own confirmed action through the screen.
|
|
63
|
+
|
|
64
|
+
## Examples
|
|
65
|
+
|
|
66
|
+
SDK, wired to a confirm step:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
// src/features/admin/roles/useAssignPermissions.ts
|
|
70
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
71
|
+
import { blocksClient } from "../../../lib/blocks/client";
|
|
72
|
+
|
|
73
|
+
export function useAssignPermissions() {
|
|
74
|
+
const queryClient = useQueryClient();
|
|
75
|
+
return useMutation({
|
|
76
|
+
mutationFn: (delta: { slug: string; addPermissions: string[]; removePermissions: string[] }) =>
|
|
77
|
+
blocksClient.iam.roles.assignPermissions(delta),
|
|
78
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["iam", "roles"] })
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// in the role editor component, only after the admin reviews a diff and clicks "Save":
|
|
85
|
+
const assign = useAssignPermissions();
|
|
86
|
+
const onConfirmSave = () =>
|
|
87
|
+
assign.mutate({ slug: role.slug, addPermissions: pendingAdds, removePermissions: pendingRemoves });
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The equivalent from a terminal, doing the same review-then-confirm dance the CLI enforces natively:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
blocks use my-tenant-id # or pass --project my-tenant-id on every call below
|
|
94
|
+
blocks iam roles create --name Editor --description "Content editors" --dry-run
|
|
95
|
+
# review the printed request body, then:
|
|
96
|
+
blocks iam roles create --name Editor --description "Content editors" --yes
|
|
97
|
+
|
|
98
|
+
blocks iam roles assign-permissions editor --add-permissions content::publish --dry-run
|
|
99
|
+
blocks iam roles assign-permissions editor --add-permissions content::publish --yes
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Gotchas
|
|
103
|
+
|
|
104
|
+
- **CLI mutations are project-scoped, not account-scoped** — `blocks iam roles create/update/assign-permissions` and `blocks iam permissions create/update` all require a selected project (`blocks use <tenantId>` or `--project <tenantId>`) and run against the impersonated-project token; `blocks iam me` is the one IAM command that uses the account token instead, so don't expect `iam me`'s auth context to carry over to these.
|
|
105
|
+
- **Role hierarchy and permission assignment key off `slug`**, not `itemId` — grab it from `roles.list()`/`roles.get()` (or `blocks iam roles list/get`) before calling `assignPermissions`.
|
|
106
|
+
- **`roles.assignPermissions` is additive/subtractive** (`addPermissions[]` / `removePermissions[]` in one call), not a full-set replace — compute the delta from what's checked/unchecked, don't resend the entire permission list as "adds."
|
|
107
|
+
- **`roles.assignable()` scopes to the caller** — always populate role pickers from it rather than `roles.list()`, so an admin can't be shown (or attempt to grant) a role above their own authority.
|
|
108
|
+
- **Never fire a create/update/assign-permissions call — CLI or SDK — without a human confirming that specific change first** (a reviewed `--dry-run` plus explicit go-ahead on the CLI, an explicit in-UI confirm for the SDK) — no auto-provisioning "default roles," no agent-initiated cleanup of permissions, no batch edits without a per-change confirm.
|
|
109
|
+
- **OIDC/identity-provider client provisioning is always portal-only**, independent of everything above — if a request drifts into "create an OIDC client" or "add an identity provider," that's a different skill's territory (or no skill's — send the user to the portal), not something to bolt onto this one.
|