@greenpandastudios/aug-cli 0.19.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/bin/aug.mjs +12 -2
- package/docs/about.md +27 -0
- package/docs/api/crypto.md +103 -69
- package/docs/api/io.md +35 -33
- package/docs/api/json.md +3 -3
- package/docs/api/memory.md +23 -19
- package/docs/api/time.md +10 -9
- package/docs/api/web.md +33 -38
- package/docs/compatibility.md +3 -3
- package/docs/contributing-benchmarks.md +38 -0
- package/docs/dev-containers.md +95 -0
- package/docs/diagnostics.md +15 -5
- package/docs/docker.md +174 -12
- package/docs/editor.md +35 -0
- package/docs/example-projects.json +206 -24
- package/docs/examples/approved-design/counters.md +34 -126
- package/docs/examples/approved-design/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/approved-design/domain/app.md +13 -77
- package/docs/examples/approved-design/domain/export.md +5 -19
- package/docs/examples/approved-design/domain/models.md +4 -23
- package/docs/examples/approved-design/domain/numbers.md +24 -114
- package/docs/examples/approved-design/index.md +16 -7
- package/docs/examples/approved-design/main.md +19 -96
- package/docs/examples/benchmark/index.md +6 -5
- package/docs/examples/benchmark/main.md +7 -35
- package/docs/examples/cli-args/index.md +6 -5
- package/docs/examples/cli-args/main.md +6 -31
- package/docs/examples/collections/index.md +6 -5
- package/docs/examples/collections/main.md +7 -35
- package/docs/examples/collections-benchmark/index.md +6 -5
- package/docs/examples/collections-benchmark/main.md +7 -35
- package/docs/examples/cpu-benchmark/index.md +6 -5
- package/docs/examples/cpu-benchmark/main.md +5 -24
- package/docs/examples/developer-workflow/calculator.md +39 -186
- package/docs/examples/developer-workflow/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/developer-workflow/index.md +16 -7
- package/docs/examples/developer-workflow/logging/console.md +10 -56
- package/docs/examples/developer-workflow/logging/export.md +4 -14
- package/docs/examples/developer-workflow/logging/logger.md +7 -43
- package/docs/examples/developer-workflow/main.md +17 -69
- package/docs/examples/drop/index.md +6 -5
- package/docs/examples/drop/main.md +7 -27
- package/docs/examples/drop/resource.md +7 -30
- package/docs/examples/errors/errors.md +7 -27
- package/docs/examples/errors/index.md +6 -5
- package/docs/examples/errors/main.md +7 -28
- package/docs/examples/ffi/index.md +6 -5
- package/docs/examples/ffi/main.md +6 -20
- package/docs/examples/ffi/native.md +8 -34
- package/docs/examples/generic-di/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/generic-di/index.md +6 -5
- package/docs/examples/generic-di/main.md +9 -39
- package/docs/examples/generic-di/types.md +23 -92
- package/docs/examples/generics/index.md +6 -5
- package/docs/examples/generics/main.md +10 -47
- package/docs/examples/generics/types.md +25 -100
- package/docs/examples/hello/app/export.md +4 -12
- package/docs/examples/hello/app/greeter.md +13 -91
- package/docs/examples/hello/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/hello/index.md +17 -6
- package/docs/examples/hello/logging/console.md +10 -54
- package/docs/examples/hello/logging/export.md +4 -14
- package/docs/examples/hello/logging/logger.md +7 -45
- package/docs/examples/hello/main.md +9 -39
- package/docs/examples/http-benchmark/index.md +6 -5
- package/docs/examples/http-benchmark/main.md +6 -20
- package/docs/examples/http-benchmark/routes.md +9 -31
- package/docs/examples/index.md +46 -29
- package/docs/examples/interceptors/app.md +20 -139
- package/docs/examples/interceptors/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/interceptors/index.md +6 -5
- package/docs/examples/interceptors/interceptors.md +24 -148
- package/docs/examples/interceptors/logging.md +13 -76
- package/docs/examples/interceptors/main.md +10 -65
- package/docs/examples/json-benchmark/data.md +4 -20
- package/docs/examples/json-benchmark/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
- package/docs/examples/json-benchmark/index.md +7 -5
- package/docs/examples/json-benchmark/main-yaml.md +20 -0
- package/docs/examples/json-benchmark/main.md +10 -49
- package/docs/examples/new-syntax/console.md +10 -52
- package/docs/examples/new-syntax/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/new-syntax/greeter.md +13 -71
- package/docs/examples/new-syntax/index.md +6 -5
- package/docs/examples/new-syntax/logger.md +7 -43
- package/docs/examples/new-syntax/main.md +10 -53
- package/docs/examples/new-syntax/math.md +6 -24
- package/docs/examples/oidc-login/client/contracts.md +10 -61
- package/docs/examples/oidc-login/client/endpoints.md +32 -154
- package/docs/examples/oidc-login/client/export.md +5 -23
- package/docs/examples/oidc-login/client/login.md +234 -344
- package/docs/examples/oidc-login/client/logout.md +38 -143
- package/docs/examples/oidc-login/client/protocol.md +183 -304
- package/docs/examples/oidc-login/client/session.md +41 -149
- package/docs/examples/oidc-login/client/views.md +13 -58
- package/docs/examples/oidc-login/common/export.md +6 -26
- package/docs/examples/oidc-login/common/headers.md +42 -72
- package/docs/examples/oidc-login/common/keys.md +40 -164
- package/docs/examples/oidc-login/common/settings.md +24 -40
- package/docs/examples/oidc-login/common/views.md +7 -28
- package/docs/examples/oidc-login/dependencies/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.md +205 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +267 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.md +415 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.md +271 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +89 -0
- package/docs/examples/oidc-login/index.md +8 -7
- package/docs/examples/oidc-login/main-yaml.md +7 -0
- package/docs/examples/oidc-login/main.md +26 -153
- package/docs/examples/oidc-login/provider/authorization.md +232 -275
- package/docs/examples/oidc-login/provider/contracts.md +24 -146
- package/docs/examples/oidc-login/provider/credentials.md +24 -57
- package/docs/examples/oidc-login/provider/discovery.md +48 -122
- package/docs/examples/oidc-login/provider/export.md +11 -37
- package/docs/examples/oidc-login/provider/token.md +159 -237
- package/docs/examples/oidc-login/provider/userinfo.md +47 -102
- package/docs/examples/oidc-login/provider/views.md +13 -53
- package/docs/examples/ownership/counter.md +17 -63
- package/docs/examples/ownership/index.md +6 -5
- package/docs/examples/ownership/main.md +7 -30
- package/docs/examples/ownership-transfer/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/ownership-transfer/index.md +6 -5
- package/docs/examples/ownership-transfer/main.md +10 -52
- package/docs/examples/ownership-transfer/resource.md +15 -67
- package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +12 -50
- package/docs/examples/packages-app/index.md +7 -6
- package/docs/examples/packages-app/main.md +7 -25
- package/docs/examples/packages-math/aug-package-json.md +1 -1
- package/docs/examples/packages-math/index.md +7 -6
- package/docs/examples/packages-math/src/arithmetic.md +12 -50
- package/docs/examples/packages-math/src/export.md +4 -12
- package/docs/examples/startup-benchmark/index.md +6 -5
- package/docs/examples/startup-benchmark/main.md +5 -17
- package/docs/examples/visibility/counter.md +19 -67
- package/docs/examples/visibility/index.md +6 -5
- package/docs/examples/visibility/main.md +7 -31
- package/docs/examples/weather-api/forecasts.md +168 -0
- package/docs/examples/weather-api/index.md +42 -0
- package/docs/examples/weather-api/main-yaml.md +21 -0
- package/docs/examples/weather-api/main.md +65 -0
- package/docs/examples.json +10 -0
- package/docs/getting-started.md +105 -2
- package/docs/grammar.md +6 -4
- package/docs/guides/change-a-module.md +64 -0
- package/docs/guides/index.md +27 -0
- package/docs/index.md +51 -29
- package/docs/language-conformance.md +1 -1
- package/docs/language-constructs.md +22 -22
- package/docs/language-design-audit.md +1 -1
- package/docs/learn/data-and-errors.md +77 -0
- package/docs/learn/index.md +30 -0
- package/docs/learn/modules-and-dependencies.md +73 -0
- package/docs/learn/state-and-tests.md +71 -0
- package/docs/learn/values-and-functions.md +62 -0
- package/docs/lesson-failures.json +8 -0
- package/docs/maintaining-docs.md +16 -4
- package/docs/packages.md +72 -126
- package/docs/performance.md +13 -41
- package/docs/production-readiness.md +5 -4
- package/docs/public/downloads/approved-design.zip +0 -0
- package/docs/public/downloads/benchmark.zip +0 -0
- package/docs/public/downloads/cli-args.zip +0 -0
- package/docs/public/downloads/collections-benchmark.zip +0 -0
- package/docs/public/downloads/collections.zip +0 -0
- package/docs/public/downloads/cpu-benchmark.zip +0 -0
- package/docs/public/downloads/developer-workflow.zip +0 -0
- package/docs/public/downloads/drop.zip +0 -0
- package/docs/public/downloads/errors.zip +0 -0
- package/docs/public/downloads/ffi.zip +0 -0
- package/docs/public/downloads/generic-di.zip +0 -0
- package/docs/public/downloads/generics.zip +0 -0
- package/docs/public/downloads/hello.zip +0 -0
- package/docs/public/downloads/http-benchmark.zip +0 -0
- package/docs/public/downloads/interceptors.zip +0 -0
- package/docs/public/downloads/json-benchmark.zip +0 -0
- package/docs/public/downloads/new-syntax.zip +0 -0
- package/docs/public/downloads/oidc-login.zip +0 -0
- package/docs/public/downloads/ownership-transfer.zip +0 -0
- package/docs/public/downloads/ownership.zip +0 -0
- package/docs/public/downloads/packages-app.zip +0 -0
- package/docs/public/downloads/packages-math.zip +0 -0
- package/docs/public/downloads/startup-benchmark.zip +0 -0
- package/docs/public/downloads/visibility.zip +0 -0
- package/docs/public/downloads/weather-api.zip +0 -0
- package/docs/reference.md +23 -17
- package/docs/releasing.md +29 -15
- package/docs/research/code-to-natural-language.md +108 -0
- package/docs/research/ecosystem-workflow.md +41 -0
- package/docs/research/wiki-editorial-design.md +71 -0
- package/docs/roadmap.md +1 -1
- package/docs/specifications.md +27 -11
- package/docs/testing.md +19 -5
- package/docs/tooling.md +25 -12
- package/docs/weather-api.md +65 -0
- package/docs/web.md +50 -18
- package/docs/writing-docs.md +49 -0
- package/examples/{hello/.aug-spec/august/0.19.0 → approved-design/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/approved-design/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/approved-design/.aug-spec/manifest.json +3 -3
- package/examples/approved-design/counters.aug +5 -4
- package/examples/approved-design/counters.aug.md +25 -132
- package/examples/approved-design/domain/app.aug +2 -1
- package/examples/approved-design/domain/app.aug.md +10 -80
- package/examples/approved-design/domain/export.aug +1 -0
- package/examples/approved-design/domain/export.aug.md +4 -20
- package/examples/approved-design/domain/models.aug +1 -0
- package/examples/approved-design/domain/models.aug.md +3 -25
- package/examples/approved-design/domain/numbers.aug +3 -2
- package/examples/approved-design/domain/numbers.aug.md +19 -116
- package/examples/approved-design/main.aug +1 -0
- package/examples/approved-design/main.aug.md +12 -95
- package/examples/benchmark/.aug-spec/manifest.json +1 -1
- package/examples/benchmark/main.aug +1 -0
- package/examples/benchmark/main.aug.md +6 -36
- package/examples/cli-args/.aug-spec/manifest.json +1 -1
- package/examples/cli-args/main.aug +1 -0
- package/examples/cli-args/main.aug.md +5 -32
- package/examples/collections/.aug-spec/manifest.json +1 -1
- package/examples/collections/main.aug +1 -0
- package/examples/collections/main.aug.md +6 -36
- package/examples/{generic-di/.aug-spec/august/0.19.0 → developer-workflow/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/developer-workflow/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
- package/examples/developer-workflow/calculator.aug +3 -2
- package/examples/developer-workflow/calculator.aug.md +28 -189
- package/examples/developer-workflow/logging/console.aug +2 -1
- package/examples/developer-workflow/logging/console.aug.md +7 -57
- package/examples/developer-workflow/logging/export.aug +1 -0
- package/examples/developer-workflow/logging/export.aug.md +3 -15
- package/examples/developer-workflow/logging/logger.aug +1 -0
- package/examples/developer-workflow/logging/logger.aug.md +6 -46
- package/examples/developer-workflow/main.aug +1 -0
- package/examples/developer-workflow/main.aug.md +10 -68
- package/examples/drop/.aug-spec/manifest.json +1 -1
- package/examples/drop/main.aug +1 -0
- package/examples/drop/main.aug.md +6 -28
- package/examples/drop/resource.aug +1 -0
- package/examples/drop/resource.aug.md +6 -34
- package/examples/errors/.aug-spec/manifest.json +1 -1
- package/examples/errors/errors.aug +2 -1
- package/examples/errors/errors.aug.md +4 -27
- package/examples/errors/main.aug +1 -0
- package/examples/errors/main.aug.md +6 -29
- package/examples/ffi/.aug-spec/manifest.json +1 -1
- package/examples/ffi/main.aug +1 -0
- package/examples/ffi/main.aug.md +5 -21
- package/examples/ffi/native.aug +2 -1
- package/examples/ffi/native.aug.md +5 -35
- package/examples/{approved-design/.aug-spec/august/0.19.0 → generic-di/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/generic-di/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/generic-di/.aug-spec/manifest.json +3 -3
- package/examples/generic-di/main.aug +1 -0
- package/examples/generic-di/main.aug.md +8 -40
- package/examples/generic-di/types.aug +3 -2
- package/examples/generic-di/types.aug.md +18 -97
- package/examples/generics/.aug-spec/manifest.json +1 -1
- package/examples/generics/main.aug +1 -0
- package/examples/generics/main.aug.md +9 -48
- package/examples/generics/types.aug +4 -3
- package/examples/generics/types.aug.md +18 -104
- package/examples/{developer-workflow/.aug-spec/august/0.19.0 → hello/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/hello/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/hello/.aug-spec/manifest.json +3 -3
- package/examples/hello/app/export.aug +1 -0
- package/examples/hello/app/export.aug.md +3 -13
- package/examples/hello/app/greeter.aug +2 -1
- package/examples/hello/app/greeter.aug.md +10 -94
- package/examples/hello/logging/console.aug +2 -1
- package/examples/hello/logging/console.aug.md +7 -55
- package/examples/hello/logging/export.aug +1 -0
- package/examples/hello/logging/export.aug.md +3 -15
- package/examples/hello/logging/logger.aug +1 -0
- package/examples/hello/logging/logger.aug.md +6 -48
- package/examples/hello/main.aug +1 -0
- package/examples/hello/main.aug.md +8 -40
- package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/interceptors/.aug-spec/manifest.json +3 -3
- package/examples/interceptors/app.aug +3 -2
- package/examples/interceptors/app.aug.md +15 -141
- package/examples/interceptors/interceptors.aug +3 -2
- package/examples/interceptors/interceptors.aug.md +19 -152
- package/examples/interceptors/logging.aug +2 -1
- package/examples/interceptors/logging.aug.md +10 -79
- package/examples/interceptors/main.aug +1 -0
- package/examples/interceptors/main.aug.md +9 -66
- package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/new-syntax/.aug-spec/manifest.json +3 -3
- package/examples/new-syntax/console.aug +2 -1
- package/examples/new-syntax/console.aug.md +7 -53
- package/examples/new-syntax/greeter.aug +2 -1
- package/examples/new-syntax/greeter.aug.md +10 -74
- package/examples/new-syntax/logger.aug +1 -0
- package/examples/new-syntax/logger.aug.md +6 -46
- package/examples/new-syntax/main.aug +1 -0
- package/examples/new-syntax/main.aug.md +9 -54
- package/examples/new-syntax/math.aug +2 -1
- package/examples/new-syntax/math.aug.md +3 -24
- package/examples/oidc-login/.aug-spec/manifest.json +13 -13
- package/examples/oidc-login/.aug-spec/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md +71 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +17 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +125 -0
- package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/contracts.aug +12 -11
- package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md +244 -0
- package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/jose.aug +6 -5
- package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md +71 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +30 -0
- package/examples/oidc-login/aug.lock.json +100 -0
- package/examples/oidc-login/client/contracts.aug +1 -0
- package/examples/oidc-login/client/contracts.aug.md +9 -66
- package/examples/oidc-login/client/endpoints.aug +6 -5
- package/examples/oidc-login/client/endpoints.aug.md +13 -145
- package/examples/oidc-login/client/export.aug +1 -0
- package/examples/oidc-login/client/export.aug.md +4 -24
- package/examples/oidc-login/client/login.aug +7 -6
- package/examples/oidc-login/client/login.aug.md +25 -303
- package/examples/oidc-login/client/logout.aug +5 -4
- package/examples/oidc-login/client/logout.aug.md +13 -135
- package/examples/oidc-login/client/protocol.aug +7 -6
- package/examples/oidc-login/client/protocol.aug.md +36 -283
- package/examples/oidc-login/client/session.aug +5 -4
- package/examples/oidc-login/client/session.aug.md +12 -139
- package/examples/oidc-login/client/views.aug +3 -2
- package/examples/oidc-login/client/views.aug.md +8 -57
- package/examples/oidc-login/common/export.aug +1 -0
- package/examples/oidc-login/common/export.aug.md +5 -27
- package/examples/oidc-login/common/headers.aug +4 -3
- package/examples/oidc-login/common/headers.aug.md +9 -67
- package/examples/oidc-login/common/keys.aug +6 -5
- package/examples/oidc-login/common/keys.aug.md +29 -165
- package/examples/oidc-login/common/settings.aug +2 -1
- package/examples/oidc-login/common/settings.aug.md +5 -39
- package/examples/oidc-login/common/views.aug +2 -1
- package/examples/oidc-login/common/views.aug.md +4 -28
- package/examples/oidc-login/main.aug +6 -16
- package/examples/oidc-login/main.aug.md +17 -146
- package/examples/oidc-login/main.yaml +7 -0
- package/examples/oidc-login/provider/authorization.aug +7 -6
- package/examples/oidc-login/provider/authorization.aug.md +23 -238
- package/examples/oidc-login/provider/contracts.aug +1 -0
- package/examples/oidc-login/provider/contracts.aug.md +23 -158
- package/examples/oidc-login/provider/credentials.aug +3 -2
- package/examples/oidc-login/provider/credentials.aug.md +9 -53
- package/examples/oidc-login/provider/discovery.aug +4 -3
- package/examples/oidc-login/provider/discovery.aug.md +11 -118
- package/examples/oidc-login/provider/export.aug +1 -0
- package/examples/oidc-login/provider/export.aug.md +6 -34
- package/examples/oidc-login/provider/token.aug +6 -5
- package/examples/oidc-login/provider/token.aug.md +16 -204
- package/examples/oidc-login/provider/userinfo.aug +4 -3
- package/examples/oidc-login/provider/userinfo.aug.md +10 -92
- package/examples/oidc-login/provider/views.aug +3 -2
- package/examples/oidc-login/provider/views.aug.md +8 -52
- package/examples/ownership/.aug-spec/manifest.json +1 -1
- package/examples/ownership/counter.aug +3 -2
- package/examples/ownership/counter.aug.md +12 -66
- package/examples/ownership/main.aug +1 -0
- package/examples/ownership/main.aug.md +6 -31
- package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
- package/examples/ownership-transfer/main.aug +1 -0
- package/examples/ownership-transfer/main.aug.md +9 -53
- package/examples/ownership-transfer/resource.aug +2 -1
- package/examples/ownership-transfer/resource.aug.md +12 -71
- package/examples/packages/app/.aug-spec/manifest.json +1 -1
- package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +2 -1
- package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +9 -51
- package/examples/packages/app/main.aug +1 -0
- package/examples/packages/app/main.aug.md +6 -26
- package/examples/packages/math/.aug-spec/manifest.json +1 -1
- package/examples/packages/math/aug-package.json +1 -1
- package/examples/packages/math/src/arithmetic.aug +2 -1
- package/examples/packages/math/src/arithmetic.aug.md +9 -51
- package/examples/packages/math/src/export.aug +1 -0
- package/examples/packages/math/src/export.aug.md +3 -13
- package/examples/visibility/.aug-spec/manifest.json +1 -1
- package/examples/visibility/counter.aug +4 -3
- package/examples/visibility/counter.aug.md +12 -68
- package/examples/visibility/main.aug +1 -0
- package/examples/visibility/main.aug.md +6 -32
- package/examples/weather-api/.aug-spec/manifest.json +8 -0
- package/examples/weather-api/AGENTS.md +17 -0
- package/examples/weather-api/README.md +19 -0
- package/examples/weather-api/forecasts.aug +47 -0
- package/examples/weather-api/forecasts.aug.md +32 -0
- package/examples/weather-api/main.aug +4 -0
- package/examples/weather-api/main.aug.md +15 -0
- package/examples/weather-api/main.yaml +5 -0
- package/examples/weather-api/weather.http +5 -0
- package/package.json +3 -4
- package/scripts/bootstrap-native.mjs +181 -106
- package/scripts/native-setup.mjs +98 -0
- package/scripts/native-toolchain.mjs +28 -0
- package/src/builtins.js +1 -1
- package/src/checker.js +259 -72
- package/src/cli.js +114 -20
- package/src/codegen.js +1 -1
- package/src/config.js +1 -1
- package/src/contracts.js +10 -0
- package/src/editor.js +71 -16
- package/src/fixes.js +90 -2
- package/src/formatter.js +19 -8
- package/src/git-packages.js +110 -0
- package/src/help.js +24 -23
- package/src/http-contracts.js +14 -0
- package/src/http-policies.js +5 -5
- package/src/libraries.js +1 -1
- package/src/lsp.js +14 -5
- package/src/native.js +19 -13
- package/src/navigation.js +4 -2
- package/src/openapi.js +5 -4
- package/src/package-locking.js +45 -0
- package/src/package-manager.js +251 -67
- package/src/parser.js +13 -5
- package/src/policies.js +3 -3
- package/src/project-init.js +78 -4
- package/src/project.js +9 -7
- package/src/semantic.js +46 -2
- package/src/snippets.js +59 -0
- package/src/spec-hints.js +56 -0
- package/src/spec-tree.js +241 -0
- package/src/spec.js +626 -303
- package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +0 -103
- package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +0 -925
- package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +0 -434
- package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +0 -103
- package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +0 -374
- package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +0 -150
- package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +0 -532
- package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +0 -791
- package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +0 -266
- package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +0 -55
- package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +0 -250
- package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +0 -96
- package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +0 -420
- package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/memory → packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/store.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/json → packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/web → packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/time → packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
|
@@ -1,331 +1,53 @@
|
|
|
1
1
|
<!-- Generated by aug spec. Edit the August source, then regenerate. -->
|
|
2
2
|
|
|
3
|
-
# `login.aug`
|
|
3
|
+
# `login.aug`
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## In this file
|
|
8
|
-
|
|
9
|
-
- [`startLogin`](login.aug.md#symbol-startLogin) handles `GET` `/login/start` returning `HttpResponse<Html>`.
|
|
10
|
-
- [`loginCallback`](login.aug.md#symbol-loginCallback) handles `GET` `/login/callback` returning `HttpResponse<Html>`.
|
|
5
|
+
Plain handler results default to HTTP 200 unless another status is declared. HttpResponse values choose their own status. Unhandled request failures return HTTP 500 and cancel the request tasks.
|
|
11
6
|
|
|
12
7
|
<a id="symbol-startLogin"></a>
|
|
8
|
+
## `startLogin` · [source](login.aug#L12)
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[source](login.aug#L11)
|
|
17
|
-
|
|
18
|
-
**Inputs**
|
|
19
|
-
|
|
20
|
-
- `crypto` ([`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto)) — injected; callers omit it.
|
|
21
|
-
- `clock` ([`Clock`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock)) — injected; callers omit it.
|
|
22
|
-
- `client` ([`HttpClient`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient)) — injected; callers omit it.
|
|
23
|
-
- `transactions` ([`ExpiringStore<LoginTransaction>`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore)) — injected; callers omit it.
|
|
24
|
-
|
|
25
|
-
Returns: `HttpResponse<Html>`.
|
|
10
|
+
`startLogin` handles `GET /login/start`. Start a browser-bound, short-lived transaction. The PKCE verifier stays on the server. It gets `crypto` ([`Crypto`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto)), `clock` ([`Clock`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock)), `client` ([`HttpClient`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient)), and `transactions` ([`ExpiringStore<LoginTransaction>`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore)) from dependency injection.
|
|
26
11
|
|
|
27
|
-
|
|
12
|
+
The handler responds with HTTP 502 for [`SessionError`](contracts.aug.md#symbol-SessionError), HTTP 503 for `CryptoError`, HTTP 503 for `TimeError`, and HTTP 503 for [`StoreFull`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-StoreFull). It can also raise `HttpError`.
|
|
28
13
|
|
|
29
|
-
|
|
14
|
+
It gets `config` from [`settings`](../common/settings.aug.md#symbol-settings). It gets `document` from [`discover`](protocol.aug.md#symbol-discover) using injected `client`. It sets `browser`, `state`, `nonce`, and `verifier` separately, each to the URL-safe base64 encoding of [`crypto.random`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.random) with `size` `32`. It sets `transaction` to a [`LoginTransaction`](contracts.aug.md#symbol-LoginTransaction) with `state`, `nonce`, `verifier`, and `expires` from [`clock.now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now) plus `300`.
|
|
30
15
|
|
|
31
|
-
|
|
16
|
+
It calls [`transactions.put`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.put) with `key` from `browser`, `value` from `transaction`, `transaction.expires`, and `now` from [`clock.now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now). It sets `challenge` to the URL-safe base64 encoding of [`crypto.sha256`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.sha256) with `input` from the UTF-8 bytes of `verifier`. It builds `location` as the text `{document.authorization_endpoint}?response_type=code&client_id={urlEncode with input from config.clientId}&redirect_uri={urlEncode with input from config.callback}&scope=openid%20profile&state={urlEncode with input from state}&nonce={urlEncode with input from nonce}&code_challenge={urlEncode with input from challenge}&code_challenge_method=S256`. It sets `headers` to [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` from [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) with the header `"location"` set to `location`, `name` `"aug_login"`, `value` from `browser`, `path` `"/login"`, `maxAge` `300`, and `secure` from `config.secureCookies`.
|
|
32
17
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
**What it does**
|
|
36
|
-
|
|
37
|
-
- Set `config` to call [`settings`](../common/settings.aug.md#symbol-settings).
|
|
38
|
-
- Set `document` to call [`discover`](protocol.aug.md#symbol-discover); inject `client` from `client`.
|
|
39
|
-
- Set `browser` to call `base64url` on call [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) on `crypto` with `size` = `32`.
|
|
40
|
-
- Set `state` to call `base64url` on call [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) on `crypto` with `size` = `32`.
|
|
41
|
-
- Set `nonce` to call `base64url` on call [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) on `crypto` with `size` = `32`.
|
|
42
|
-
- Set `verifier` to call `base64url` on call [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) on `crypto` with `size` = `32`.
|
|
43
|
-
- Set `transaction` to call [`LoginTransaction`](contracts.aug.md#symbol-LoginTransaction) with `state` = `state`; `nonce` = `nonce`; `verifier` = `verifier`; `expires` = (call [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) on `clock` plus `300`).
|
|
44
|
-
- Call [`ExpiringStore.put`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.put) on `transactions` with `key` = `browser`; `value` = `transaction`; `expires` = `expires` of `transaction`; `now` = call [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) on `clock`.
|
|
45
|
-
- Set `challenge` to call `base64url` on call [`Crypto.sha256`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.sha256) on `crypto` with `input` = call `bytes` on `verifier`.
|
|
46
|
-
- Build `location` by joining these text parts without separators, in order:
|
|
47
|
-
1. `authorization_endpoint` of `document`
|
|
48
|
-
2. `"?response_type=code&client_id="`
|
|
49
|
-
3. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `clientId` of `config`
|
|
50
|
-
4. `"&redirect_uri="`
|
|
51
|
-
5. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `callback` of `config`
|
|
52
|
-
6. `"&scope=openid%20profile&state="`
|
|
53
|
-
7. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `state`
|
|
54
|
-
8. `"&nonce="`
|
|
55
|
-
9. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `nonce`
|
|
56
|
-
10. `"&code_challenge="`
|
|
57
|
-
11. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `challenge`
|
|
58
|
-
12. `"&code_challenge_method=S256"`
|
|
59
|
-
- Set `headers` to call [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` = call `with` on call [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) with `name` = `"location"`; `value` = `location`; `name` = `"aug_login"`; `value` = `browser`; `path` = `"/login"`; `maxAge` = `300`; `secure` = `secureCookies` of `config`.
|
|
60
|
-
- Return call `HttpResponse` with `body` = the HTML element `p` containing `Opening the identity provider.` (rendered on the server with embedded text escaped); `status` = `303`; `headers` = `headers`.
|
|
61
|
-
|
|
62
|
-
**Author documentation**
|
|
63
|
-
|
|
64
|
-
Start a browser-bound, short-lived transaction. The PKCE verifier stays on the server.
|
|
18
|
+
It returns HTTP 303 with a paragraph containing `Opening the identity provider.` with escaped text and `headers` headers.
|
|
65
19
|
|
|
66
20
|
<a id="symbol-loginCallback"></a>
|
|
21
|
+
## `loginCallback` · [source](login.aug#L27)
|
|
67
22
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
[source](login.aug#L26)
|
|
71
|
-
|
|
72
|
-
**Inputs**
|
|
73
|
-
|
|
74
|
-
- `code` (`string`) — read from the HTTP query.
|
|
75
|
-
- `state` (`string`) — read from the HTTP query.
|
|
76
|
-
- `browser` (`optional string`) — read from the HTTP cookie named `aug_login`; absent value becomes null.
|
|
77
|
-
- `crypto` ([`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto)) — injected; callers omit it.
|
|
78
|
-
- `clock` ([`Clock`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock)) — injected; callers omit it.
|
|
79
|
-
- `client` ([`HttpClient`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient)) — injected; callers omit it.
|
|
80
|
-
- `keys` ([`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys)) — injected; callers omit it.
|
|
81
|
-
- `transactions` ([`ExpiringStore<LoginTransaction>`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore)) — injected; callers omit it.
|
|
82
|
-
- `sessions` ([`ExpiringStore<SessionClaims>`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore)) — injected; callers omit it.
|
|
83
|
-
|
|
84
|
-
Returns: `HttpResponse<Html>`.
|
|
85
|
-
|
|
86
|
-
Capabilities: [`crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal), [`crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random), [`crypto.signRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.signRsa), [`crypto.decodeBase64url`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.decodeBase64url), [`crypto.importRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.importRsa), [`crypto.verifyRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.verifyRsa), [`clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now), [`client.request`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient.request), [`keys.session`](../common/keys.aug.md#symbol-SigningKeys.session), [`transactions.take`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.take), [`sessions.put`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.put).
|
|
87
|
-
|
|
88
|
-
Can fail with `SessionError`, `CryptoError`, `TimeError`, `KeyError`, `StoreFull`, `JwtError`, `JsonError`, `HttpError`. Callers must catch or propagate these errors.
|
|
89
|
-
|
|
90
|
-
HTTP route: `GET` `/login/callback`. Use status 200 when the handler returns a body; a returned HttpResponse can set its own status. An unhandled request failure returns status 500 and cancels its request tasks.
|
|
91
|
-
|
|
92
|
-
Declared HTTP failures: [`SessionError`](contracts.aug.md#symbol-SessionError) returns status 400; `CryptoError` returns status 503; `TimeError` returns status 503; [`StoreFull`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-StoreFull) returns status 503.
|
|
93
|
-
|
|
94
|
-
**What it does**
|
|
95
|
-
|
|
96
|
-
- If not (call `isToken` on `code` with `min` = `43`; `max` = `43`) or not (call `isToken` on `state` with `min` = `43`; `max` = `43`):
|
|
97
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
98
|
-
- Select the matching case for `browser`:
|
|
99
|
-
- A null value, including omitted optional input:
|
|
100
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
101
|
-
- A present, non-null value, named `secret`:
|
|
102
|
-
- Select the matching case for call [`ExpiringStore.take`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.take) on `transactions` with `key` = `secret`; `now` = call [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) on `clock`:
|
|
103
|
-
- A null value, including omitted optional input:
|
|
104
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
105
|
-
- A present, non-null value, named `transaction`:
|
|
106
|
-
- If not (call [`Crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal) on `crypto` with `left` = call `bytes` on `state` of `transaction`; `right` = call `bytes` on `state`):
|
|
107
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
108
|
-
- Set `config` to call [`settings`](../common/settings.aug.md#symbol-settings).
|
|
109
|
-
- Set `document` to call [`discover`](protocol.aug.md#symbol-discover); inject `client` from `client`.
|
|
110
|
-
- Build `body` by joining these text parts without separators, in order:
|
|
111
|
-
1. `"grant_type=authorization_code&code="`
|
|
112
|
-
2. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `code`
|
|
113
|
-
3. `"&redirect_uri="`
|
|
114
|
-
4. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `callback` of `config`
|
|
115
|
-
5. `"&client_id="`
|
|
116
|
-
6. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `clientId` of `config`
|
|
117
|
-
7. `"&code_verifier="`
|
|
118
|
-
8. call [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) with `input` = `verifier` of `transaction`
|
|
119
|
-
- Set `headers` to call `with` on call `Headers` with `name` = `"content-type"`; `value` = `"application/x-www-form-urlencoded"`.
|
|
120
|
-
- Set `tokens` to call `decode` on call [`responseJson`](protocol.aug.md#symbol-responseJson) with `response` = call [`HttpClient.request`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient.request) on `client` with `method` = `"POST"`; `url` = `token_endpoint` of `document`; `headers` = `headers`; `body` = call `bytes` on `body` with type arguments [`TokenResponse`](../provider/contracts.aug.md#symbol-TokenResponse).
|
|
121
|
-
- If ((`token_type` of `tokens` does not equal `"Bearer"`) or not (call `isToken` on `access_token` of `tokens` with `min` = `43`; `max` = `43`)) or (`expires_in` of `tokens` is at most `0`):
|
|
122
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
123
|
-
- Set `jwks` to call `decode` on call [`responseJson`](protocol.aug.md#symbol-responseJson) with `response` = call [`HttpClient.request`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient.request) on `client` with `method` = `"GET"`; `url` = `jwks_uri` of `document` with type arguments [`RsaJwks`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-RsaJwks).
|
|
124
|
-
- Set `identity` to call [`validateIdentity`](protocol.aug.md#symbol-validateIdentity) with `token` = `id_token` of `tokens`; `nonce` = `nonce` of `transaction`; `now` = call [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) on `clock`; `jwks` = `jwks`; inject `crypto` from `crypto`.
|
|
125
|
-
- Set `authHeaders` to call `with` on call `Headers` with `name` = `"authorization"`; `value` = (`"Bearer "` plus `access_token` of `tokens`).
|
|
126
|
-
- Set `user` to call `decode` on call [`responseJson`](protocol.aug.md#symbol-responseJson) with `response` = call [`HttpClient.request`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient.request) on `client` with `method` = `"GET"`; `url` = `userinfo_endpoint` of `document`; `headers` = `authHeaders` with type arguments [`UserInfo`](../provider/contracts.aug.md#symbol-UserInfo).
|
|
127
|
-
- If `sub` of `user` does not equal `sub` of `identity`:
|
|
128
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
129
|
-
- Set `now` to call [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) on `clock`.
|
|
130
|
-
- Set `session` to call [`SessionClaims`](contracts.aug.md#symbol-SessionClaims) with `iss` = (`baseUrl` of `config` plus `"/app"`); `sub` = `sub` of `identity`; `aud` = `"august-app"`; `exp` = (`now` plus `sessionSeconds` of `config`); `iat` = `now`; `jti` = call `base64url` on call [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) on `crypto` with `size` = `32`; `csrf` = call `base64url` on call [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) on `crypto` with `size` = `32`; `name` = `name` of `user`.
|
|
131
|
-
- Set `jwt` to call [`signJwt`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-signJwt) with `key` = call [`SigningKeys.session`](../common/keys.aug.md#symbol-SigningKeys.session) on `keys`; `claims` = call `Json` with `value` = `session`; `kid` = `"session-1"`; `tokenType` = `"august-session+jwt"`; inject `crypto` from `crypto`.
|
|
132
|
-
- Call [`ExpiringStore.put`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.put) on `sessions` with `key` = `jti` of `session`; `value` = `session`; `expires` = `exp` of `session`; `now` = `now`.
|
|
133
|
-
- Set `responseHeaders` to call [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` = call `with` on call [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) with `name` = `"location"`; `value` = `"/"`; `name` = `"aug_session"`; `value` = `jwt`; `path` = `"/"`; `maxAge` = `sessionSeconds` of `config`; `secure` = `secureCookies` of `config`.
|
|
134
|
-
- Set `responseHeaders` to call [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` = `responseHeaders`; `name` = `"aug_login"`; `value` = `""`; `path` = `"/login"`; `maxAge` = `0`; `secure` = `secureCookies` of `config`.
|
|
135
|
-
- Return call `HttpResponse` with `body` = the HTML element `p` containing `Signed in.` (rendered on the server with embedded text escaped); `status` = `303`; `headers` = `responseHeaders`.
|
|
136
|
-
|
|
137
|
-
**Author documentation**
|
|
138
|
-
|
|
139
|
-
Exchange a one-use code over HTTP, verify the provider JWT/JWKS and UserInfo subject, then issue a distinct app-session JWT.
|
|
140
|
-
|
|
141
|
-
## Dependencies used by this file
|
|
142
|
-
|
|
143
|
-
Only referenced types and operations appear here. Each name links to its complete specification.
|
|
144
|
-
|
|
145
|
-
### [`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto)
|
|
146
|
-
|
|
147
|
-
Capability interface from `august.crypto`.
|
|
148
|
-
|
|
149
|
-
- [`Crypto.decodeBase64url`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.decodeBase64url) (`input`: `string`) → `Bytes`; can fail with `CryptoError`.
|
|
150
|
-
- [`Crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal) (`left`: `Bytes`, `right`: `Bytes`) → `bool`.
|
|
151
|
-
- [`Crypto.importRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.importRsa) (`modulus`: `Bytes`, `exponent`: `Bytes`) → `RsaPublicKey`; can fail with `CryptoError`.
|
|
152
|
-
- [`Crypto.random`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.random) (`size`: `int`) → `Bytes`; can fail with `CryptoError`.
|
|
153
|
-
- [`Crypto.sha256`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.sha256) (`input`: `Bytes`) → `Bytes`; can fail with `CryptoError`.
|
|
154
|
-
- [`Crypto.signRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.signRsa) (`key`: `RsaPrivateKey`, `input`: `Bytes`) → `Bytes`; can fail with `CryptoError`.
|
|
155
|
-
- [`Crypto.verifyRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.verifyRsa) (`publicKey`: `RsaPublicKey`, `input`: `Bytes`, `signature`: `Bytes`) → `bool`; can fail with `CryptoError`.
|
|
156
|
-
|
|
157
|
-
### [`JwtError`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-JwtError)
|
|
158
|
-
|
|
159
|
-
Class from `august.crypto`.
|
|
160
|
-
|
|
161
|
-
Used as a type or provider.
|
|
162
|
-
|
|
163
|
-
### [`RsaJwks`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-RsaJwks)
|
|
164
|
-
|
|
165
|
-
Record from `august.crypto`.
|
|
166
|
-
|
|
167
|
-
Used as a type or provider.
|
|
168
|
-
|
|
169
|
-
### [`signJwt`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-signJwt)
|
|
170
|
-
|
|
171
|
-
Function from `august.crypto`.
|
|
172
|
-
|
|
173
|
-
- [`signJwt`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-signJwt) (`key`: `RsaPrivateKey`, `claims`: `Json`, `kid`: `string`, `tokenType`: `string`) → `string`; inject `crypto`: [`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto); uses [`crypto.signRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.signRsa); can fail with `JwtError`.
|
|
174
|
-
|
|
175
|
-
### [`ExpiringStore`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore)
|
|
176
|
-
|
|
177
|
-
Capability interface from `august.memory`.
|
|
178
|
-
|
|
179
|
-
- [`ExpiringStore.put`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.put) (`key`: `string`, `value`: `T`, `expires`: `int`, `now`: `int`) → `void`; can fail with `StoreFull`.
|
|
180
|
-
- [`ExpiringStore.take`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.take) (`key`: `string`, `now`: `int`) → `optional T`.
|
|
181
|
-
|
|
182
|
-
### [`StoreFull`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-StoreFull)
|
|
183
|
-
|
|
184
|
-
Class from `august.memory`.
|
|
185
|
-
|
|
186
|
-
Used as a type or provider.
|
|
187
|
-
|
|
188
|
-
### [`Clock`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock)
|
|
189
|
-
|
|
190
|
-
Capability interface from `august.time`.
|
|
191
|
-
|
|
192
|
-
- [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) (no caller inputs) → `int`; can fail with `TimeError`.
|
|
193
|
-
|
|
194
|
-
### [`HttpClient`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient)
|
|
195
|
-
|
|
196
|
-
Capability interface from `august.web`.
|
|
197
|
-
|
|
198
|
-
- [`HttpClient.request`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient.request) (`method`: `string`, `url`: `string`, `headers`: `optional Headers`, `body`: `optional Bytes`) → `HttpResponse<Bytes>`; can fail with `HttpError`.
|
|
199
|
-
|
|
200
|
-
### [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode)
|
|
201
|
-
|
|
202
|
-
Function from `august.web`.
|
|
203
|
-
|
|
204
|
-
- [`urlEncode`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-urlEncode) (`input`: `string`) → `string`; can fail with `HttpError`.
|
|
205
|
-
|
|
206
|
-
### [`LoginTransaction`](contracts.aug.md#symbol-LoginTransaction)
|
|
207
|
-
|
|
208
|
-
Record from `contracts`.
|
|
209
|
-
|
|
210
|
-
- Construct with `state`: `string`, `nonce`: `string`, `verifier`: `string`, `expires`: `int` → [`LoginTransaction`](contracts.aug.md#symbol-LoginTransaction).
|
|
211
|
-
- Read `expires` (`int`).
|
|
212
|
-
- Read `nonce` (`string`).
|
|
213
|
-
- Read `state` (`string`).
|
|
214
|
-
- Read `verifier` (`string`).
|
|
215
|
-
|
|
216
|
-
### [`SessionClaims`](contracts.aug.md#symbol-SessionClaims)
|
|
217
|
-
|
|
218
|
-
Record from `contracts`.
|
|
219
|
-
|
|
220
|
-
- Construct with `iss`: `string`, `sub`: `string`, `aud`: `string`, `exp`: `int`, `iat`: `int`, `jti`: `string`, `csrf`: `string`, `name`: `string` → [`SessionClaims`](contracts.aug.md#symbol-SessionClaims).
|
|
221
|
-
- Read `exp` (`int`).
|
|
222
|
-
- Read `jti` (`string`).
|
|
223
|
-
|
|
224
|
-
### [`SessionError`](contracts.aug.md#symbol-SessionError)
|
|
225
|
-
|
|
226
|
-
Class from `contracts`.
|
|
227
|
-
|
|
228
|
-
- Construct with no caller inputs → [`SessionError`](contracts.aug.md#symbol-SessionError).
|
|
229
|
-
|
|
230
|
-
### [`discover`](protocol.aug.md#symbol-discover)
|
|
231
|
-
|
|
232
|
-
Function from `protocol`.
|
|
233
|
-
|
|
234
|
-
- [`discover`](protocol.aug.md#symbol-discover) (no caller inputs) → [`Discovery`](../provider/discovery.aug.md#symbol-Discovery); inject `client`: [`HttpClient`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient); uses [`client.request`](../.aug-spec/august/0.19.0/web/contracts.aug.md#symbol-HttpClient.request); can fail with `SessionError`, `HttpError`.
|
|
235
|
-
|
|
236
|
-
### [`responseJson`](protocol.aug.md#symbol-responseJson)
|
|
237
|
-
|
|
238
|
-
Function from `protocol`.
|
|
239
|
-
|
|
240
|
-
- [`responseJson`](protocol.aug.md#symbol-responseJson) (`response`: `HttpResponse<Bytes>`) → `Json`; can fail with `SessionError`.
|
|
241
|
-
|
|
242
|
-
### [`validateIdentity`](protocol.aug.md#symbol-validateIdentity)
|
|
243
|
-
|
|
244
|
-
Function from `protocol`.
|
|
245
|
-
|
|
246
|
-
- [`validateIdentity`](protocol.aug.md#symbol-validateIdentity) (`token`: `string`, `nonce`: `string`, `now`: `int`, `jwks`: [`RsaJwks`](../.aug-spec/august/0.19.0/crypto/jose.aug.md#symbol-RsaJwks)) → [`IdClaims`](../provider/contracts.aug.md#symbol-IdClaims); inject `crypto`: [`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto); uses [`crypto.decodeBase64url`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.decodeBase64url), [`crypto.importRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.importRsa), [`crypto.verifyRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.verifyRsa), [`crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal); can fail with `SessionError`.
|
|
247
|
-
|
|
248
|
-
### [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders)
|
|
249
|
-
|
|
250
|
-
Function from `common`.
|
|
251
|
-
|
|
252
|
-
- [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) (no caller inputs) → `Headers`; can fail with `HttpError`.
|
|
253
|
-
|
|
254
|
-
### [`withCookie`](../common/headers.aug.md#symbol-withCookie)
|
|
255
|
-
|
|
256
|
-
Function from `common`.
|
|
257
|
-
|
|
258
|
-
- [`withCookie`](../common/headers.aug.md#symbol-withCookie) (`headers`: `Headers`, `name`: `string`, `value`: `string`, `path`: `string`, `maxAge`: `int`, `secure`: `bool`) → `Headers`; can fail with `HttpError`.
|
|
259
|
-
|
|
260
|
-
### [`KeyError`](../common/keys.aug.md#symbol-KeyError)
|
|
261
|
-
|
|
262
|
-
Class from `common`.
|
|
263
|
-
|
|
264
|
-
Used as a type or provider.
|
|
265
|
-
|
|
266
|
-
### [`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys)
|
|
267
|
-
|
|
268
|
-
Capability interface from `common`.
|
|
269
|
-
|
|
270
|
-
- [`SigningKeys.session`](../common/keys.aug.md#symbol-SigningKeys.session) (no caller inputs) → `RsaPrivateKey`; can fail with `KeyError`.
|
|
271
|
-
|
|
272
|
-
### [`Settings`](../common/settings.aug.md#symbol-Settings)
|
|
273
|
-
|
|
274
|
-
Record.
|
|
275
|
-
|
|
276
|
-
- Read `baseUrl` (`string`).
|
|
277
|
-
- Read `callback` (`string`).
|
|
278
|
-
- Read `clientId` (`string`).
|
|
279
|
-
- Read `secureCookies` (`bool`).
|
|
280
|
-
- Read `sessionSeconds` (`int`).
|
|
281
|
-
|
|
282
|
-
### [`settings`](../common/settings.aug.md#symbol-settings)
|
|
283
|
-
|
|
284
|
-
Function from `common`.
|
|
285
|
-
|
|
286
|
-
- [`settings`](../common/settings.aug.md#symbol-settings) (no caller inputs) → [`Settings`](../common/settings.aug.md#symbol-Settings).
|
|
287
|
-
|
|
288
|
-
### [`IdClaims`](../provider/contracts.aug.md#symbol-IdClaims)
|
|
289
|
-
|
|
290
|
-
Record.
|
|
23
|
+
`loginCallback` handles `GET /login/callback`. Exchange a one-use code over HTTP, verify the provider JWT/JWKS and UserInfo subject, then issue a distinct app-session JWT.
|
|
291
24
|
|
|
292
|
-
-
|
|
25
|
+
It takes `code` and `state` as strings from the HTTP query and `browser` as `optional string` from the HTTP cookie `aug_login`. It gets `crypto` ([`Crypto`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto)), `clock` ([`Clock`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock)), `client` ([`HttpClient`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient)), `keys` ([`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys)), `transactions` ([`ExpiringStore<LoginTransaction>`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore)), and `sessions` ([`ExpiringStore<SessionClaims>`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore)) from dependency injection. Omitted optional inputs are null. The handler responds with HTTP 400 for [`SessionError`](contracts.aug.md#symbol-SessionError), HTTP 503 for `CryptoError`, HTTP 503 for `TimeError`, and HTTP 503 for [`StoreFull`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-StoreFull).
|
|
293
26
|
|
|
294
|
-
|
|
27
|
+
It can also raise `HttpError`, `JsonError`, `JwtError`, and `KeyError`.
|
|
295
28
|
|
|
296
|
-
|
|
29
|
+
It checks that `code` is a URL-safe ASCII token with `43` to `43` characters and `state` is a URL-safe ASCII token with `43` to `43` characters. It raises a [`SessionError`](contracts.aug.md#symbol-SessionError) at the first failed check. If `browser` is null, it raises a [`SessionError`](contracts.aug.md#symbol-SessionError). The non-null `browser` becomes `secret`.
|
|
297
30
|
|
|
298
|
-
-
|
|
299
|
-
- Read `expires_in` (`int`).
|
|
300
|
-
- Read `id_token` (`string`).
|
|
301
|
-
- Read `token_type` (`string`).
|
|
31
|
+
It obtains [`transactions.take`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.take) with `key` from `secret` and `now` from [`clock.now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now). If no value is found, it raises a [`SessionError`](contracts.aug.md#symbol-SessionError). The non-null result becomes `transaction`.
|
|
302
32
|
|
|
303
|
-
|
|
33
|
+
It checks that [`crypto.equal`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.equal) with `left` from the UTF-8 bytes of `transaction.state` and `right` from the UTF-8 bytes of `state` returns true. It raises a [`SessionError`](contracts.aug.md#symbol-SessionError) at the first failed check. It gets `config` from [`settings`](../common/settings.aug.md#symbol-settings). It gets `document` from [`discover`](protocol.aug.md#symbol-discover) using injected `client`.
|
|
304
34
|
|
|
305
|
-
|
|
35
|
+
It builds `body` as the text `grant_type=authorization_code&code={urlEncode with input from code}&redirect_uri={urlEncode with input from config.callback}&client_id={urlEncode with input from config.clientId}&code_verifier={urlEncode with input from transaction.verifier}`. It sets `headers` to a `Headers` with the header `"content-type"` set to `"application/x-www-form-urlencoded"`. It sets `tokens` to `decode` on [`responseJson`](protocol.aug.md#symbol-responseJson) with `response` from [`client.request`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient.request) with `method` `"POST"`, `url` from `document.token_endpoint`, `headers`, and `body` from the UTF-8 bytes of `body` for [`TokenResponse`](../provider/contracts.aug.md#symbol-TokenResponse).
|
|
306
36
|
|
|
307
|
-
-
|
|
308
|
-
- Read `sub` (`string`).
|
|
37
|
+
It checks that `tokens.token_type` equals `"Bearer"` and `tokens.access_token` is a URL-safe ASCII token with `43` to `43` characters and `tokens.expires_in` is greater than `0`. It raises a [`SessionError`](contracts.aug.md#symbol-SessionError) at the first failed check. It sets `jwks` to `decode` on [`responseJson`](protocol.aug.md#symbol-responseJson) with `response` from [`client.request`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient.request) with `method` `"GET"` and `url` from `document.jwks_uri` for [`RsaJwks`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md#symbol-RsaJwks). It sets `identity` to [`validateIdentity`](protocol.aug.md#symbol-validateIdentity) with `token` from `tokens.id_token`, `transaction.nonce`, `now` from [`clock.now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now), and `jwks` using injected `crypto`.
|
|
309
38
|
|
|
310
|
-
|
|
39
|
+
It sets `authHeaders` to a `Headers` with the header `"authorization"` set to the text `Bearer {tokens.access_token}`. It sets `user` to `decode` on [`responseJson`](protocol.aug.md#symbol-responseJson) with `response` from [`client.request`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient.request) with `method` `"GET"`, `url` from `document.userinfo_endpoint`, and `headers` from `authHeaders` for [`UserInfo`](../provider/contracts.aug.md#symbol-UserInfo). It checks that `user.sub` equals `identity.sub`. It raises a [`SessionError`](contracts.aug.md#symbol-SessionError) at the first failed check.
|
|
311
40
|
|
|
312
|
-
|
|
41
|
+
It sets `now` to [`clock.now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now). It sets `session` to a [`SessionClaims`](contracts.aug.md#symbol-SessionClaims) with `iss` from the text `{config.baseUrl}/app`, `identity.sub`, `aud` `"august-app"`, `exp` from `now` plus `config.sessionSeconds`, `iat` from `now`, `jti` from the URL-safe base64 encoding of [`crypto.random`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.random) with `size` `32`, `csrf` from the URL-safe base64 encoding of [`crypto.random`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.random) with `size` `32`, and `user.name`. It sets `jwt` to [`signJwt`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md#symbol-signJwt) with `key` from [`keys.session`](../common/keys.aug.md#symbol-SigningKeys.session), `claims` from a `Json` with `value` from `session`, `kid` `"session-1"`, and `tokenType` `"august-session+jwt"` using injected `crypto`. It calls [`sessions.put`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.put) with `key` from `session.jti`, `value` from `session`, `expires` from `session.exp`, and `now`.
|
|
313
42
|
|
|
314
|
-
-
|
|
315
|
-
- Read `jwks_uri` (`string`).
|
|
316
|
-
- Read `token_endpoint` (`string`).
|
|
317
|
-
- Read `userinfo_endpoint` (`string`).
|
|
43
|
+
It sets `responseHeaders` to [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` from [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) with the header `"location"` set to `"/"`, `name` `"aug_session"`, `value` from `jwt`, `path` `"/"`, `maxAge` from `config.sessionSeconds`, and `secure` from `config.secureCookies`. It sets `responseHeaders` to [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` from `responseHeaders`, `name` `"aug_login"`, `value` `""`, `path` `"/login"`, `maxAge` `0`, and `secure` from `config.secureCookies`. It returns HTTP 303 with a paragraph containing `Signed in.` with escaped text and `responseHeaders` headers.
|
|
318
44
|
|
|
319
|
-
##
|
|
45
|
+
## Dependencies
|
|
320
46
|
|
|
321
|
-
- `
|
|
322
|
-
- `Headers.with` (`name`: `string`, `value`: `string`) → `Headers`: Return new headers with one additional validated field. Header names ignore case; duplicate values remain separate. Can fail with `HttpError`.
|
|
323
|
-
- `Json.decode` (no inputs) → `UserInfo`: Decode a checked record or data type: json.decode<Profile>(). Unknown fields, type mismatches, and validation errors are rejected. Can fail with `JsonError`.
|
|
324
|
-
- `string.bytes` (no inputs) → `Bytes`: Encode this string as immutable UTF-8 bytes.
|
|
325
|
-
- `string.isToken` (`min`: `int`, `max`: `int`) → `bool`: Require an ASCII RFC 3986 unreserved token with a bounded length.
|
|
47
|
+
It uses [`ExpiringStore`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore) ([`put`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.put) and [`take`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.take)) and [`StoreFull`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-StoreFull) from `memory`. It uses [`HttpClient`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient) ([`request`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-HttpClient.request)) and [`urlEncode`](../.aug-spec/packages/%40git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-urlEncode) from `web`. It uses [`Crypto`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto) ([`decodeBase64url`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.decodeBase64url), [`equal`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.equal), [`importRsa`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.importRsa), [`random`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.random), [`sha256`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.sha256), [`signRsa`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.signRsa), and [`verifyRsa`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.verifyRsa)), [`JwtError`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md#symbol-JwtError), [`RsaJwks`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md#symbol-RsaJwks), and [`signJwt`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md#symbol-signJwt) from `crypto`. It uses [`Clock`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock) ([`now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now)) from `time`.
|
|
326
48
|
|
|
327
|
-
[
|
|
49
|
+
It uses [`LoginTransaction`](contracts.aug.md#symbol-LoginTransaction) (`expires`, `nonce`, `state`, and `verifier`), [`SessionClaims`](contracts.aug.md#symbol-SessionClaims) (`exp` and `jti`), and [`SessionError`](contracts.aug.md#symbol-SessionError) from `contracts`. It uses [`discover`](protocol.aug.md#symbol-discover), [`responseJson`](protocol.aug.md#symbol-responseJson), and [`validateIdentity`](protocol.aug.md#symbol-validateIdentity) from `protocol`. It uses [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders), [`withCookie`](../common/headers.aug.md#symbol-withCookie), [`KeyError`](../common/keys.aug.md#symbol-KeyError), [`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys) ([`session`](../common/keys.aug.md#symbol-SigningKeys.session)), and [`settings`](../common/settings.aug.md#symbol-settings) from `common`. It uses [`Settings`](../common/settings.aug.md#symbol-Settings) (`baseUrl`, `callback`, `clientId`, `secureCookies`, and `sessionSeconds`), [`IdClaims`](../provider/contracts.aug.md#symbol-IdClaims) (`sub`), and [`Discovery`](../provider/discovery.aug.md#symbol-Discovery) (`authorization_endpoint`, `jwks_uri`, `token_endpoint`, and `userinfo_endpoint`).
|
|
328
50
|
|
|
329
|
-
|
|
51
|
+
It uses [`TokenResponse`](../provider/contracts.aug.md#symbol-TokenResponse) (`access_token`, `expires_in`, `id_token`, and `token_type`) and [`UserInfo`](../provider/contracts.aug.md#symbol-UserInfo) (`name` and `sub`) from `provider`.
|
|
330
52
|
|
|
331
|
-
|
|
53
|
+
Built-in operations follow the [language reference](https://greenpandastudios.github.io/augscript/language-constructs).
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
// aug-spec: "logout.aug.md" explains this file. Read it before changes; refresh with aug spec.
|
|
1
2
|
import SessionClaims and SessionError and LogoutForm from contracts
|
|
2
3
|
import authenticate from session
|
|
3
4
|
import settings and SigningKeys and KeyError and securityHeaders and withCookie from common
|
|
4
|
-
import Crypto from
|
|
5
|
-
import Clock from
|
|
6
|
-
import ExpiringStore from
|
|
5
|
+
import Crypto from crypto
|
|
6
|
+
import Clock from time
|
|
7
|
+
import ExpiringStore from memory
|
|
7
8
|
|
|
8
9
|
/** POST logout checks the origin and session-bound CSRF value, then removes the live registry entry before clearing the cookie. */
|
|
9
|
-
endpoint POST "/logout" as logout(LogoutForm input from form, optional string token from cookie "aug_session", optional string origin from header, resolve Crypto crypto, resolve Clock clock, resolve SigningKeys keys, resolve ExpiringStore<SessionClaims> sessions)
|
|
10
|
+
endpoint POST "/logout" as logout(LogoutForm input from form, optional string token from cookie "aug_session", optional string origin from header, resolve Crypto crypto, resolve Clock clock, resolve SigningKeys keys, resolve ExpiringStore<SessionClaims> sessions) unless SessionError with status 403 and KeyError and TimeError and CryptoError and HttpError:
|
|
10
11
|
config = settings()
|
|
11
12
|
if origin != config.baseUrl:
|
|
12
13
|
throw SessionError()
|
|
@@ -1,150 +1,28 @@
|
|
|
1
1
|
<!-- Generated by aug spec. Edit the August source, then regenerate. -->
|
|
2
2
|
|
|
3
|
-
# `logout.aug`
|
|
3
|
+
# `logout.aug`
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## In this file
|
|
8
|
-
|
|
9
|
-
- [`logout`](logout.aug.md#symbol-logout) handles `POST` `/logout` returning `HttpResponse<Html>`.
|
|
5
|
+
Plain handler results default to HTTP 200 unless another status is declared. HttpResponse values choose their own status. Unhandled request failures return HTTP 500 and cancel the request tasks.
|
|
10
6
|
|
|
11
7
|
<a id="symbol-logout"></a>
|
|
8
|
+
## `logout` · [source](logout.aug#L10)
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
[source](logout.aug#L9)
|
|
16
|
-
|
|
17
|
-
**Inputs**
|
|
18
|
-
|
|
19
|
-
- `input` ([`LogoutForm`](contracts.aug.md#symbol-LogoutForm)) — read from the HTTP form.
|
|
20
|
-
- `token` (`optional string`) — read from the HTTP cookie named `aug_session`; absent value becomes null.
|
|
21
|
-
- `origin` (`optional string`) — read from the HTTP header; absent value becomes null.
|
|
22
|
-
- `crypto` ([`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto)) — injected; callers omit it.
|
|
23
|
-
- `clock` ([`Clock`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock)) — injected; callers omit it.
|
|
24
|
-
- `keys` ([`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys)) — injected; callers omit it.
|
|
25
|
-
- `sessions` ([`ExpiringStore<SessionClaims>`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore)) — injected; callers omit it.
|
|
26
|
-
|
|
27
|
-
Returns: `HttpResponse<Html>`.
|
|
28
|
-
|
|
29
|
-
Capabilities: [`crypto.publicRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.publicRsa), [`crypto.decodeBase64url`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.decodeBase64url), [`crypto.verifyRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.verifyRsa), [`crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal), [`clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now), [`keys.session`](../common/keys.aug.md#symbol-SigningKeys.session), [`sessions.get`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.get), [`sessions.take`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.take).
|
|
30
|
-
|
|
31
|
-
Can fail with `SessionError`, `KeyError`, `TimeError`, `CryptoError`, `HttpError`. Callers must catch or propagate these errors.
|
|
32
|
-
|
|
33
|
-
HTTP route: `POST` `/logout`. Use status 200 when the handler returns a body; a returned HttpResponse can set its own status. An unhandled request failure returns status 500 and cancels its request tasks.
|
|
34
|
-
|
|
35
|
-
Declared HTTP failures: [`SessionError`](contracts.aug.md#symbol-SessionError) returns status 403.
|
|
36
|
-
|
|
37
|
-
**What it does**
|
|
38
|
-
|
|
39
|
-
- Set `config` to call [`settings`](../common/settings.aug.md#symbol-settings).
|
|
40
|
-
- If `origin` does not equal `baseUrl` of `config`:
|
|
41
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
42
|
-
- Set `session` to call [`authenticate`](session.aug.md#symbol-authenticate) with `token` = `token`; inject `crypto` from `crypto`, `clock` from `clock`, `keys` from `keys`, `sessions` from `sessions`.
|
|
43
|
-
- If not (call [`Crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal) on `crypto` with `left` = call `bytes` on `csrf` of `input`; `right` = call `bytes` on `csrf` of `session`):
|
|
44
|
-
- Fail with call [`SessionError`](contracts.aug.md#symbol-SessionError). Transfer control to a matching catch or propagate the failure.
|
|
45
|
-
- Call [`ExpiringStore.take`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.take) on `sessions` with `key` = `jti` of `session`; `now` = call [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) on `clock`.
|
|
46
|
-
- Set `headers` to call [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` = call `with` on call [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) with `name` = `"location"`; `value` = `"/"`; `name` = `"aug_session"`; `value` = `""`; `path` = `"/"`; `maxAge` = `0`; `secure` = `secureCookies` of `config`.
|
|
47
|
-
- Return call `HttpResponse` with `body` = the HTML element `p` containing `Signed out.` (rendered on the server with embedded text escaped); `status` = `303`; `headers` = `headers`.
|
|
48
|
-
|
|
49
|
-
**Author documentation**
|
|
50
|
-
|
|
51
|
-
POST logout checks the origin and session-bound CSRF value, then removes the live registry entry before clearing the cookie.
|
|
52
|
-
|
|
53
|
-
## Dependencies used by this file
|
|
54
|
-
|
|
55
|
-
Only referenced types and operations appear here. Each name links to its complete specification.
|
|
56
|
-
|
|
57
|
-
### [`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto)
|
|
58
|
-
|
|
59
|
-
Capability interface from `august.crypto`.
|
|
60
|
-
|
|
61
|
-
- [`Crypto.decodeBase64url`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.decodeBase64url) (`input`: `string`) → `Bytes`; can fail with `CryptoError`.
|
|
62
|
-
- [`Crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal) (`left`: `Bytes`, `right`: `Bytes`) → `bool`.
|
|
63
|
-
- [`Crypto.publicRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.publicRsa) (`key`: `RsaPrivateKey`) → `RsaPublicKey`; can fail with `CryptoError`.
|
|
64
|
-
- [`Crypto.verifyRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.verifyRsa) (`publicKey`: `RsaPublicKey`, `input`: `Bytes`, `signature`: `Bytes`) → `bool`; can fail with `CryptoError`.
|
|
65
|
-
|
|
66
|
-
### [`ExpiringStore`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore)
|
|
67
|
-
|
|
68
|
-
Capability interface from `august.memory`.
|
|
69
|
-
|
|
70
|
-
- [`ExpiringStore.get`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.get) (`key`: `string`, `now`: `int`) → `optional T`.
|
|
71
|
-
- [`ExpiringStore.take`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.take) (`key`: `string`, `now`: `int`) → `optional T`.
|
|
72
|
-
|
|
73
|
-
### [`Clock`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock)
|
|
74
|
-
|
|
75
|
-
Capability interface from `august.time`.
|
|
76
|
-
|
|
77
|
-
- [`Clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now) (no caller inputs) → `int`; can fail with `TimeError`.
|
|
78
|
-
|
|
79
|
-
### [`LogoutForm`](contracts.aug.md#symbol-LogoutForm)
|
|
80
|
-
|
|
81
|
-
Record from `contracts`.
|
|
82
|
-
|
|
83
|
-
- Read `csrf` (`string`).
|
|
84
|
-
|
|
85
|
-
### [`SessionClaims`](contracts.aug.md#symbol-SessionClaims)
|
|
86
|
-
|
|
87
|
-
Record from `contracts`.
|
|
88
|
-
|
|
89
|
-
- Read `csrf` (`string`).
|
|
90
|
-
- Read `jti` (`string`).
|
|
91
|
-
|
|
92
|
-
### [`SessionError`](contracts.aug.md#symbol-SessionError)
|
|
93
|
-
|
|
94
|
-
Class from `contracts`.
|
|
95
|
-
|
|
96
|
-
- Construct with no caller inputs → [`SessionError`](contracts.aug.md#symbol-SessionError).
|
|
97
|
-
|
|
98
|
-
### [`authenticate`](session.aug.md#symbol-authenticate)
|
|
99
|
-
|
|
100
|
-
Function from `session`.
|
|
101
|
-
|
|
102
|
-
- [`authenticate`](session.aug.md#symbol-authenticate) (`token`: `optional string`) → [`SessionClaims`](contracts.aug.md#symbol-SessionClaims); inject `crypto`: [`Crypto`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto), `clock`: [`Clock`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock), `keys`: [`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys), `sessions`: [`ExpiringStore<SessionClaims>`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore); uses [`crypto.publicRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.publicRsa), [`crypto.decodeBase64url`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.decodeBase64url), [`crypto.verifyRsa`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.verifyRsa), [`crypto.equal`](../.aug-spec/august/0.19.0/crypto/contracts.aug.md#symbol-Crypto.equal), [`clock.now`](../.aug-spec/august/0.19.0/time/contracts.aug.md#symbol-Clock.now), [`keys.session`](../common/keys.aug.md#symbol-SigningKeys.session), [`sessions.get`](../.aug-spec/august/0.19.0/memory/store.aug.md#symbol-ExpiringStore.get); can fail with `SessionError`, `KeyError`, `TimeError`.
|
|
103
|
-
|
|
104
|
-
### [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders)
|
|
105
|
-
|
|
106
|
-
Function from `common`.
|
|
107
|
-
|
|
108
|
-
- [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) (no caller inputs) → `Headers`; can fail with `HttpError`.
|
|
109
|
-
|
|
110
|
-
### [`withCookie`](../common/headers.aug.md#symbol-withCookie)
|
|
111
|
-
|
|
112
|
-
Function from `common`.
|
|
113
|
-
|
|
114
|
-
- [`withCookie`](../common/headers.aug.md#symbol-withCookie) (`headers`: `Headers`, `name`: `string`, `value`: `string`, `path`: `string`, `maxAge`: `int`, `secure`: `bool`) → `Headers`; can fail with `HttpError`.
|
|
115
|
-
|
|
116
|
-
### [`KeyError`](../common/keys.aug.md#symbol-KeyError)
|
|
117
|
-
|
|
118
|
-
Class from `common`.
|
|
119
|
-
|
|
120
|
-
Used as a type or provider.
|
|
121
|
-
|
|
122
|
-
### [`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys)
|
|
123
|
-
|
|
124
|
-
Capability interface from `common`.
|
|
125
|
-
|
|
126
|
-
- [`SigningKeys.session`](../common/keys.aug.md#symbol-SigningKeys.session) (no caller inputs) → `RsaPrivateKey`; can fail with `KeyError`.
|
|
127
|
-
|
|
128
|
-
### [`Settings`](../common/settings.aug.md#symbol-Settings)
|
|
129
|
-
|
|
130
|
-
Record.
|
|
10
|
+
`logout` handles `POST /logout`. POST logout checks the origin and session-bound CSRF value, then removes the live registry entry before clearing the cookie.
|
|
131
11
|
|
|
132
|
-
|
|
133
|
-
- Read `secureCookies` (`bool`).
|
|
12
|
+
It takes `input` as [`LogoutForm`](contracts.aug.md#symbol-LogoutForm) from the HTTP form, `token` as `optional string` from the HTTP cookie `aug_session`, and `origin` as `optional string` from the HTTP header. It gets `crypto` ([`Crypto`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto)), `clock` ([`Clock`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock)), `keys` ([`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys)), and `sessions` ([`ExpiringStore<SessionClaims>`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore)) from dependency injection. Omitted optional inputs are null. The handler responds with HTTP 403 for [`SessionError`](contracts.aug.md#symbol-SessionError).
|
|
134
13
|
|
|
135
|
-
|
|
14
|
+
It can also raise `CryptoError`, `HttpError`, `KeyError`, and `TimeError`.
|
|
136
15
|
|
|
137
|
-
|
|
16
|
+
It gets `config` from [`settings`](../common/settings.aug.md#symbol-settings). It checks that `origin` equals `config.baseUrl`. It raises a [`SessionError`](contracts.aug.md#symbol-SessionError) at the first failed check. It sets `session` to [`authenticate`](session.aug.md#symbol-authenticate) with `token` using injected `crypto`, `clock`, `keys`, and `sessions`.
|
|
138
17
|
|
|
139
|
-
- [`
|
|
18
|
+
It checks that [`crypto.equal`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.equal) with `left` from the UTF-8 bytes of `input.csrf` and `right` from the UTF-8 bytes of `session.csrf` returns true. It raises a [`SessionError`](contracts.aug.md#symbol-SessionError) at the first failed check. It calls [`sessions.take`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.take) with `key` from `session.jti` and `now` from [`clock.now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now). It sets `headers` to [`withCookie`](../common/headers.aug.md#symbol-withCookie) with `headers` from [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders) with the header `"location"` set to `"/"`, `name` `"aug_session"`, `value` `""`, `path` `"/"`, `maxAge` `0`, and `secure` from `config.secureCookies`.
|
|
140
19
|
|
|
141
|
-
|
|
20
|
+
It returns HTTP 303 with a paragraph containing `Signed out.` with escaped text and `headers` headers.
|
|
142
21
|
|
|
143
|
-
|
|
144
|
-
- `string.bytes` (no inputs) → `Bytes`: Encode this string as immutable UTF-8 bytes.
|
|
22
|
+
## Dependencies
|
|
145
23
|
|
|
146
|
-
[
|
|
24
|
+
It uses [`ExpiringStore`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore) ([`get`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.get) and [`take`](../.aug-spec/packages/%40git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md#symbol-ExpiringStore.take)) from `memory`. It uses [`Crypto`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto) ([`decodeBase64url`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.decodeBase64url), [`equal`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.equal), [`publicRsa`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.publicRsa), and [`verifyRsa`](../.aug-spec/packages/%40git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md#symbol-Crypto.verifyRsa)) from `crypto`. It uses [`Clock`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock) ([`now`](../.aug-spec/packages/%40git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md#symbol-Clock.now)) from `time`. It uses [`LogoutForm`](contracts.aug.md#symbol-LogoutForm) (`csrf`), [`SessionClaims`](contracts.aug.md#symbol-SessionClaims) (`csrf` and `jti`), and [`SessionError`](contracts.aug.md#symbol-SessionError) from `contracts`.
|
|
147
25
|
|
|
148
|
-
|
|
26
|
+
It uses [`authenticate`](session.aug.md#symbol-authenticate) from `session`. It uses [`securityHeaders`](../common/headers.aug.md#symbol-securityHeaders), [`withCookie`](../common/headers.aug.md#symbol-withCookie), [`KeyError`](../common/keys.aug.md#symbol-KeyError), [`SigningKeys`](../common/keys.aug.md#symbol-SigningKeys) ([`session`](../common/keys.aug.md#symbol-SigningKeys.session)), and [`settings`](../common/settings.aug.md#symbol-settings) from `common`. It uses [`Settings`](../common/settings.aug.md#symbol-Settings) (`baseUrl` and `secureCookies`).
|
|
149
27
|
|
|
150
|
-
|
|
28
|
+
Built-in operations follow the [language reference](https://greenpandastudios.github.io/augscript/language-constructs).
|