├── .DS_Store ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── docs ├── fonts │ ├── slate.eot │ ├── slate.svg │ ├── slate.ttf │ ├── slate.woff │ └── slate.woff2 ├── images │ ├── clientCredentialsSequence.png │ ├── holderDomain.png │ ├── logo.png │ ├── logoSanta.png │ ├── navbar.png │ ├── redirPartA.png │ ├── redirPartB.png │ └── redirPartC.png ├── index.html ├── javascripts │ ├── all.js │ └── all_nosearch.js └── stylesheets │ ├── print.css │ └── screen.css ├── slate ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Vagrantfile ├── build.sh ├── config.rb ├── deploy.sh ├── font-selection.json ├── lib │ ├── multilang.rb │ ├── nesting_unique_head.rb │ ├── toc_data.rb │ └── unique_head.rb ├── run.sh └── source │ ├── fonts │ ├── slate.eot │ ├── slate.svg │ ├── slate.ttf │ ├── slate.woff │ └── slate.woff2 │ ├── images │ ├── clientCredentialsSequence.png │ ├── holderDomain.png │ ├── logo.png │ ├── logoSanta.png │ ├── navbar.png │ ├── redirPartA.png │ ├── redirPartB.png │ └── redirPartC.png │ ├── index.html.md │ ├── javascripts │ ├── all.js │ ├── all_nosearch.js │ ├── app │ │ ├── _lang.js │ │ ├── _search.js │ │ └── _toc.js │ └── lib │ │ ├── _energize.js │ │ ├── _imagesloaded.min.js │ │ ├── _jquery.highlight.js │ │ ├── _jquery.js │ │ └── _lunr.js │ ├── layouts │ └── layout.erb │ └── stylesheets │ ├── _icon-font.scss │ ├── _normalize.scss │ ├── _rtl.scss │ ├── _variables.scss │ ├── print.css.scss │ └── screen.css.scss └── workshops ├── InfoSecWorkshop06122018.pdf └── InfoSecWorkshop16112018.pdf /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | *.DS_STORE 15 | build/ 16 | .cache 17 | .vagrant 18 | .sass-cache 19 | 20 | # YARD artifacts 21 | .yardoc 22 | _yardoc 23 | doc/ 24 | .idea/ 25 | 26 | .DS_Store 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [0.0.1+1] - 2018-11-23 10 | ### Added 11 | - First draft of CDR Info Sec Profile 12 | 13 | ## [0.0.1+2] - 2018-11-24 14 | ### Added 15 | - Change log [#5](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/5) 16 | 17 | ### Fixed 18 | - Bug [#3](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/3) 19 | 20 | ## [0.0.2+1] - 2018-11-30 21 | ### Added 22 | - Published 0.0.2 build 1. 23 | 24 | ### Fixed 25 | - Bug [#16] (https://github.com/ConsumerDataStandardsAustralia/infosec/issues/16) 26 | 27 | ## [0.0.2+2] - 2018-12-08 28 | ### Added 29 | - Todos for linking directly to relevant part(s) of specifications. 30 | 31 | ### Fixed 32 | - Various typographical errors. 33 | - Padding of time values in date times per ISO8601. 34 | - Made it clearer which values are being referred to in _Hashing value for state and authorisation code_. 35 | 36 | ## [0.0.3+1] - 2018-12-11 37 | ### Added 38 | - Define Normative and Non-Normative elements - Feature [#24](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/24). 39 | - Clarify Request Object Content - Feature [#13](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/13). 40 | - Consent and Authorisation - Feature [#12](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/12) 41 | - Refine Introspection Endpoint section - Feature [#11](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/11) 42 | - Add Vectors of Trust - Feature [#10](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/10) 43 | - Update LoAs with LoA 2 [#4](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/4) 44 | 45 | ## [0.0.3+2] - 2018-12-14 46 | ### Fixed 47 | - Typographic errors. 48 | 49 | ## [0.0.3+3] - 2018-12-14 50 | ### Changed 51 | - X1254 is now an informative reference - Feature [#37](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/37). 52 | 53 | ### Added 54 | - 12.2 might imply vectors of trust is required. Feature [#30](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/30) 55 | 56 | ### Fixed 57 | - Add `essential` field in examples of essential claims - Bug [#29](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/29) 58 | 59 | ## [0.0.3+4] - 2018-12-18 60 | 61 | ### Fixed 62 | - Improved clarity of document. 63 | - Simplified introduction. 64 | - CIBA is now FAPI-CIBA 65 | - Fixed some typographic errors. 66 | - Replaced customer with consumer. 67 | - Removed references to accreditation of Data Holder. 68 | - Holder and Recipient are now Data Holder and Data Recipient. 69 | - `iss` claim is not supported on request object. 70 | - `iat` claim in not mandatory as part of private key client authentication JWT. 71 | - `bc-authorize` is now `backchannel_authentication_endpoint` on OIDD. 72 | - *user* is now *end-user* in appendix. 73 | 74 | ## [0.0.3+5] - 2018-12-19 75 | 76 | ### Fixed 77 | - Bug with consent id outside of claims [#42](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/42) 78 | 79 | ## [0.1.0+1] - 2018-12-20 80 | ### Added 81 | - Published 0.1.0 build 1. 82 | 83 | ## [0.1.1+1] - 2019-01-07 84 | ### Added 85 | - Published 0.1.1 build 1. 86 | - Only private key JWT will be supported as outlined in proposal [Client Authentication - Private Key Support Only #7](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/7) 87 | - Sector URIs will be supported. This issue is discussed under issue [#48](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/48). 88 | 89 | ## [0.1.1+2] - 2019-01-07 90 | ### Added 91 | - Reflect FAPI and CIBA Core updates in Profile as per feature issue [#50](https://github.com/ConsumerDataStandardsAustralia/infosec/issues/50). 92 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Data61 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Consumer Data Right Information Security Profile 2 | 3 | ## Please note that this repository is now deprecated and is retained to maintain change and consultation History 4 | 5 | 6 | Ongoing development of the Information Security Profile for CDR is being conducted in the main CDR Standards repository at https://github.com/ConsumerDataStandardsAustralia/standards 7 | 8 | Maintenance is being conducted on the standards maintenance repository at https://github.com/ConsumerDataStandardsAustralia/standards-maintenance 9 | -------------------------------------------------------------------------------- /docs/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/fonts/slate.eot -------------------------------------------------------------------------------- /docs/fonts/slate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/fonts/slate.ttf -------------------------------------------------------------------------------- /docs/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/fonts/slate.woff -------------------------------------------------------------------------------- /docs/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/fonts/slate.woff2 -------------------------------------------------------------------------------- /docs/images/clientCredentialsSequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/clientCredentialsSequence.png -------------------------------------------------------------------------------- /docs/images/holderDomain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/holderDomain.png -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/logoSanta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/logoSanta.png -------------------------------------------------------------------------------- /docs/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/navbar.png -------------------------------------------------------------------------------- /docs/images/redirPartA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/redirPartA.png -------------------------------------------------------------------------------- /docs/images/redirPartB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/redirPartB.png -------------------------------------------------------------------------------- /docs/images/redirPartC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/docs/images/redirPartC.png -------------------------------------------------------------------------------- /docs/stylesheets/print.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.content h1,.content h2,.content h3,.content h4,body{font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size:14px}.content h1,.content h2,.content h3,.content h4{font-weight:bold}.content pre,.content code{font-family:Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;font-size:12px;line-height:1.5}.content pre,.content code{word-break:break-all;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}@font-face{font-family:'slate';src:url(../fonts/slate.eot?-syv14m);src:url(../fonts/slate.eot?#iefix-syv14m) format("embedded-opentype"),url(../fonts/slate.woff2?-syv14m) format("woff2"),url(../fonts/slate.woff?-syv14m) format("woff"),url(../fonts/slate.ttf?-syv14m) format("truetype"),url(../fonts/slate.svg?-syv14m#slate) format("svg");font-weight:normal;font-style:normal}.content aside.warning:before,.content aside.notice:before,.content aside.success:before{font-family:'slate';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1}.content aside.warning:before{content:"\e600"}.content aside.notice:before{content:"\e602"}.content aside.success:before{content:"\e606"}.tocify,.toc-footer,.lang-selector,.search,#nav-button{display:none}.tocify-wrapper>img{margin:0 auto;display:block}.logo{background-color:black;margin-bottom:10px;width:100%}.content{font-size:12px}.content pre,.content code{border:1px solid #999;border-radius:5px;font-size:0.8em}.content pre code{border:0}.content pre{padding:1.3em}.content code{padding:0.2em}.content table{border:1px solid #999}.content table tr{border-bottom:1px solid #999}.content table td,.content table th{padding:0.7em}.content p{line-height:1.5}.content a{text-decoration:none;color:#000}.content h1{font-size:2.5em;padding-top:0.5em;padding-bottom:0.5em;margin-top:1em;margin-bottom:21px;border:2px solid #ccc;border-width:2px 0;text-align:center;page-break-before:always}.content h2{font-size:1.8em;margin-top:2em;border-top:2px solid #ccc;padding-top:0.8em}.content h1+h2,.content h1+div+h2{border-top:none;padding-top:0;margin-top:0}.content h3,.content h4{font-size:0.8em;margin-top:1.5em;margin-bottom:0.8em;text-transform:uppercase}.content h5,.content h6{text-transform:uppercase}.content aside{padding:1em;border:1px solid #ccc;border-radius:5px;margin-top:1.5em;margin-bottom:1.5em;line-height:1.6}.content aside:before{vertical-align:middle;padding-right:0.5em;font-size:14px} -------------------------------------------------------------------------------- /docs/stylesheets/screen.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6,html,body{font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size:14px}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{font-weight:bold}.content code,.content pre{font-family:Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;font-size:12px;line-height:1.5}.content code{word-break:break-all;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}@font-face{font-family:'slate';src:url(../fonts/slate.eot?-syv14m);src:url(../fonts/slate.eot?#iefix-syv14m) format("embedded-opentype"),url(../fonts/slate.woff2?-syv14m) format("woff2"),url(../fonts/slate.woff?-syv14m) format("woff"),url(../fonts/slate.ttf?-syv14m) format("truetype"),url(../fonts/slate.svg?-syv14m#slate) format("svg");font-weight:normal;font-style:normal}.content aside.warning:before,.content aside.notice:before,.content aside.success:before,.toc-wrapper>.search:before{font-family:'slate';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1}.content aside.warning:before{content:"\e600"}.content aside.notice:before{content:"\e602"}.content aside.success:before{content:"\e606"}.toc-wrapper>.search:before{content:"\e607"}html,body{color:#333;padding:0;margin:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#F3F7F9;height:100%;-webkit-text-size-adjust:none}#toc>ul>li>a>span{float:right;background-color:#2484FF;border-radius:40px;width:20px}.toc-wrapper{transition:left 0.3s ease-in-out;overflow-y:auto;overflow-x:hidden;position:fixed;z-index:30;top:0;left:0;bottom:0;width:230px;background-color:#000000;font-size:13px;font-weight:bold}.toc-wrapper .lang-selector{display:none}.toc-wrapper .lang-selector a{padding-top:0.5em;padding-bottom:0.5em}.toc-wrapper .logo{display:block;max-width:100%;margin-bottom:0px}.toc-wrapper>.search{position:relative}.toc-wrapper>.search input{background:#000000;border-width:0 0 1px 0;border-color:#666;padding:6px 0 6px 20px;box-sizing:border-box;margin:10px 15px;width:200px;outline:none;color:#2FB787;border-radius:0}.toc-wrapper>.search:before{position:absolute;top:17px;left:15px;color:#2FB787}.toc-wrapper .search-results{margin-top:0;box-sizing:border-box;height:0;overflow-y:auto;overflow-x:hidden;transition-property:height, margin;transition-duration:180ms;transition-timing-function:ease-in-out;background:#1E2224}.toc-wrapper .search-results.visible{height:30%;margin-bottom:1em}.toc-wrapper .search-results li{margin:1em 15px;line-height:1}.toc-wrapper .search-results a{color:#2FB787;text-decoration:none}.toc-wrapper .search-results a:hover{text-decoration:underline}.toc-wrapper ul,.toc-wrapper li{list-style:none;margin:0;padding:0;line-height:28px}.toc-wrapper li{color:#2FB787;transition-property:background;transition-timing-function:linear;transition-duration:200ms}.toc-wrapper .toc-link.active{background-color:#00A9CE;color:#fff}.toc-wrapper .toc-link.active-parent{background-color:#1E2224;color:#2FB787}.toc-wrapper .toc-list-h2{display:none;background-color:#1E2224;font-weight:500}.toc-wrapper .toc-h2{padding-left:25px;font-size:12px}.toc-wrapper .toc-footer{padding:1em 0;margin-top:1em;border-top:1px dashed #666}.toc-wrapper .toc-footer li,.toc-wrapper .toc-footer a{color:#2FB787;text-decoration:none}.toc-wrapper .toc-footer a:hover{text-decoration:underline}.toc-wrapper .toc-footer li{font-size:0.8em;line-height:1.7;text-decoration:none}.toc-link,.toc-footer li{padding:0 15px 0 15px;display:block;overflow-x:hidden;white-space:nowrap;text-overflow:ellipsis;text-decoration:none;color:#2FB787;transition-property:background;transition-timing-function:linear;transition-duration:130ms}#nav-button{padding:0 1.5em 5em 0;display:none;position:fixed;top:0;left:0;z-index:100;color:#000;text-decoration:none;font-weight:bold;opacity:0.7;line-height:16px;transition:left 0.3s ease-in-out}#nav-button span{display:block;padding:6px 6px 6px;background-color:rgba(243,247,249,0.7);transform-origin:0 0;transform:rotate(-90deg) translate(-100%, 0);border-radius:0 0 0 5px}#nav-button img{height:16px;vertical-align:bottom}#nav-button:hover{opacity:1}#nav-button.open{left:230px}.page-wrapper{margin-left:230px;position:relative;z-index:10;background-color:#F3F7F9;min-height:100%;padding-bottom:1px}.page-wrapper .dark-box{width:40%;background-color:#2E3336;position:absolute;right:0;top:0;bottom:0}.page-wrapper .lang-selector{position:fixed;z-index:50;border-bottom:5px solid #2E3336}.lang-selector{background-color:#1E2224;width:100%;font-weight:bold}.lang-selector a{display:block;float:left;color:#fff;text-decoration:none;padding:0 10px;line-height:30px;outline:0}.lang-selector a:active,.lang-selector a:focus{background-color:#111;color:#fff}.lang-selector a.active{background-color:#2E3336;color:#fff}.lang-selector:after{content:'';clear:both;display:block}.content{-webkit-transform:translateZ(0);position:relative;z-index:30}.content:after{content:'';display:block;clear:both}.content>h1,.content>h2,.content>h3,.content>h4,.content>h5,.content>h6,.content>p,.content>table,.content>ul,.content>ol,.content>aside,.content>dl{margin-right:40%;padding:0 28px;box-sizing:border-box;display:block}.content>ul,.content>ol{padding-left:43px}.content>h1,.content>h2,.content>div{clear:both}.content h1{font-size:25px;padding-top:0.5em;padding-bottom:0.5em;margin-bottom:21px;margin-top:2em;border-top:1px solid #ccc;border-bottom:1px solid #ccc;background-color:#fdfdfd}.content h1:first-child,.content div:first-child+h1{border-top-width:0;margin-top:0}.content h2{font-size:19px;margin-top:4em;margin-bottom:0;border-top:1px solid #ccc;padding-top:1.2em;padding-bottom:1.2em;background-image:linear-gradient(to bottom, rgba(255,255,255,0.2), rgba(255,255,255,0))}.content h1+h2,.content h1+div+h2{margin-top:-21px;border-top:none}.content h3,.content h4,.content h5,.content h6{font-size:15px;margin-top:2.5em;margin-bottom:0.8em}.content h4,.content h5,.content h6{font-size:14px}.content hr{margin:2em 0;border-top:2px solid #2E3336;border-bottom:2px solid #F3F7F9}.content table{margin-bottom:1em;overflow:auto}.content table th,.content table td{text-align:left;vertical-align:top;line-height:1.6}.content table th code,.content table td code{white-space:nowrap}.content table th{padding:5px 10px;border-bottom:1px solid #ccc;vertical-align:bottom}.content table td{padding:10px}.content table tr:last-child{border-bottom:1px solid #ccc}.content table tr:nth-child(odd)>td{background-color:white}.content table tr:nth-child(even)>td{background-color:#fbfcfd}.content dt{font-weight:bold}.content dd{margin-left:15px}.content p,.content li,.content dt,.content dd{line-height:1.6;margin-top:0}.content img{max-width:100%}.content code{background-color:rgba(0,0,0,0.05);padding:3px;border-radius:3px}.content pre>code{background-color:transparent;padding:0}.content aside{padding-top:1em;padding-bottom:1em;margin-top:1.5em;margin-bottom:1.5em;background:#8fbcd4;line-height:1.6}.content aside.warning{background-color:#c97a7e}.content aside.success{background-color:#6ac174}.content aside:before{vertical-align:middle;padding-right:0.5em;font-size:14px}.content .search-highlight{padding:2px;margin:-3px;border-radius:4px;border:1px solid #F7E633;background:linear-gradient(to top left, #F7E633 0%, #F1D32F 100%)}.content pre,.content blockquote{background-color:#1E2224;color:#fff;margin:0;width:40%;float:right;clear:right;box-sizing:border-box}.content pre>p,.content blockquote>p{margin:0}.content pre a,.content blockquote a{color:#fff;text-decoration:none;border-bottom:dashed 1px #ccc}.content pre{padding-top:2em;padding-bottom:2em;padding:2em 28px}.content blockquote>p{background-color:#191D1F;padding:13px 2em;color:#eee}@media (max-width: 930px){.toc-wrapper{left:-230px}.toc-wrapper.open{left:0}.page-wrapper{margin-left:0}#nav-button{display:block}.toc-link{padding-top:0.3em;padding-bottom:0.3em}}@media (max-width: 700px){.dark-box{display:none}.content>h1,.content>h2,.content>h3,.content>h4,.content>h5,.content>h6,.content>p,.content>table,.content>ul,.content>ol,.content>aside,.content>dl{margin-right:0}.toc-wrapper .lang-selector{display:block}.page-wrapper .lang-selector{display:none}.content pre,.content blockquote{width:auto;float:none}.content>pre+h1,.content>blockquote+h1,.content>pre+h2,.content>blockquote+h2,.content>pre+h3,.content>blockquote+h3,.content>pre+h4,.content>blockquote+h4,.content>pre+h5,.content>blockquote+h5,.content>pre+h6,.content>blockquote+h6,.content>pre+p,.content>blockquote+p,.content>pre+table,.content>blockquote+table,.content>pre+ul,.content>blockquote+ul,.content>pre+ol,.content>blockquote+ol,.content>pre+aside,.content>blockquote+aside,.content>pre+dl,.content>blockquote+dl{margin-top:28px}}.highlight .c,.highlight .cm,.highlight .c1,.highlight .cs{color:#909090}.highlight,.highlight .w{background-color:#1E2224} -------------------------------------------------------------------------------- /slate/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /slate/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: ruby 4 | 5 | rvm: 6 | - 2.3.3 7 | - 2.4.0 8 | 9 | cache: bundler 10 | script: bundle exec middleman build 11 | -------------------------------------------------------------------------------- /slate/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 2.3.1 4 | 5 | *July 5, 2018* 6 | 7 | - Update `sprockets` in `Gemfile.lock` to fix security warnings 8 | 9 | ## Version 2.3 10 | 11 | *July 5, 2018* 12 | 13 | - Allows strikethrough in markdown by default. 14 | - Upgrades jQuery to 3.2.1, thanks to [Tomi Takussaari](https://github.com/TomiTakussaari) 15 | - Fixes invalid HTML in `layout.erb`, thanks to [Eric Scouten](https://github.com/scouten) for pointing out 16 | - Hopefully fixes Vagrant memory issues, thanks to [Petter Blomberg](https://github.com/p-blomberg) for the suggestion 17 | - Cleans HTML in headers before setting `document.title`, thanks to [Dan Levy](https://github.com/justsml) 18 | - Allows trailing whitespace in markdown files, thanks to [Samuel Cousin](https://github.com/kuzyn) 19 | - Fixes pushState/replaceState problems with scrolling not changing the document hash, thanks to [Andrey Fedorov](https://github.com/anfedorov) 20 | - Removes some outdated examples, thanks [@al-tr](https://github.com/al-tr), [Jerome Dahdah](https://github.com/jdahdah), and [Ricardo Castro](https://github.com/mccricardo) 21 | - Fixes `nav-padding` bug, thanks [Jerome Dahdah](https://github.com/jdahdah) 22 | - Code style fixes thanks to [Sebastian Zaremba](https://github.com/vassyz) 23 | - Nokogiri version bump thanks to [Grey Baker](https://github.com/greysteil) 24 | - Fix to default `index.md` text thanks to [Nick Busey](https://github.com/NickBusey) 25 | 26 | Thanks to everyone who contributed to this release! 27 | 28 | ## Version 2.2 29 | 30 | *January 19, 2018* 31 | 32 | - Fixes bugs with some non-roman languages not generating unique headers 33 | - Adds editorconfig, thanks to [Jay Thomas](https://github.com/jaythomas) 34 | - Adds optional `NestingUniqueHeadCounter`, thanks to [Vladimir Morozov](https://github.com/greenhost87) 35 | - Small fixes to typos and language, thx [Emir Ribić](https://github.com/ribice), [Gregor Martynus](https://github.com/gr2m), and [Martius](https://github.com/martiuslim)! 36 | - Adds links to Spectrum chat for questions in README and ISSUE_TEMPLATE 37 | 38 | ## Version 2.1 39 | 40 | *October 30, 2017* 41 | 42 | - Right-to-left text stylesheet option, thanks to [Mohammad Hossein Rabiee](https://github.com/mhrabiee) 43 | - Fix for HTML5 history state bug, thanks to [Zach Toolson](https://github.com/ztoolson) 44 | - Small styling changes, typo fixes, small bug fixes from [Marian Friedmann](https://github.com/rnarian), [Ben Wilhelm](https://github.com/benwilhelm), [Fouad Matin](https://github.com/fouad), [Nicolas Bonduel](https://github.com/NicolasBonduel), [Christian Oliff](https://github.com/coliff) 45 | 46 | Thanks to everyone who submitted PRs for this version! 47 | 48 | ## Version 2.0 49 | 50 | *July 17, 2017* 51 | 52 | - All-new statically generated table of contents 53 | - Should be much faster loading and scrolling for large pages 54 | - Smaller Javascript file sizes 55 | - Avoids the problem with the last link in the ToC not ever highlighting if the section was shorter than the page 56 | - Fixes control-click not opening in a new page 57 | - Automatically updates the HTML title as you scroll 58 | - Updated design 59 | - New default colors! 60 | - New spacings and sizes! 61 | - System-default typefaces, just like GitHub 62 | - Added search input delay on large corpuses to reduce lag 63 | - We even bumped the major version cause hey, why not? 64 | - Various small bug fixes 65 | 66 | Thanks to everyone who helped debug or wrote code for this version! It was a serious community effort, and I couldn't have done it alone. 67 | 68 | ## Version 1.5 69 | 70 | *February 23, 2017* 71 | 72 | - Add [multiple tabs per programming language](https://github.com/lord/slate/wiki/Multiple-language-tabs-per-programming-language) feature 73 | - Upgrade Middleman to add Ruby 1.4.0 compatibility 74 | - Switch default code highlighting color scheme to better highlight JSON 75 | - Various small typo and bug fixes 76 | 77 | ## Version 1.4 78 | 79 | *November 24, 2016* 80 | 81 | - Upgrade Middleman and Rouge gems, should hopefully solve a number of bugs 82 | - Update some links in README 83 | - Fix broken Vagrant startup script 84 | - Fix some problems with deploy.sh help message 85 | - Fix bug with language tabs not hiding properly if no error 86 | - Add `!default` to SASS variables 87 | - Fix bug with logo margin 88 | - Bump tested Ruby versions in .travis.yml 89 | 90 | ## Version 1.3.3 91 | 92 | *June 11, 2016* 93 | 94 | Documentation and example changes. 95 | 96 | ## Version 1.3.2 97 | 98 | *February 3, 2016* 99 | 100 | A small bugfix for slightly incorrect background colors on code samples in some cases. 101 | 102 | ## Version 1.3.1 103 | 104 | *January 31, 2016* 105 | 106 | A small bugfix for incorrect whitespace in code blocks. 107 | 108 | ## Version 1.3 109 | 110 | *January 27, 2016* 111 | 112 | We've upgraded Middleman and a number of other dependencies, which should fix quite a few bugs. 113 | 114 | Instead of `rake build` and `rake deploy`, you should now run `bundle exec middleman build --clean` to build your server, and `./deploy.sh` to deploy it to Github Pages. 115 | 116 | ## Version 1.2 117 | 118 | *June 20, 2015* 119 | 120 | **Fixes:** 121 | 122 | - Remove crash on invalid languages 123 | - Update Tocify to scroll to the highlighted header in the Table of Contents 124 | - Fix variable leak and update search algorithms 125 | - Update Python examples to be valid Python 126 | - Update gems 127 | - More misc. bugfixes of Javascript errors 128 | - Add Dockerfile 129 | - Remove unused gems 130 | - Optimize images, fonts, and generated asset files 131 | - Add chinese font support 132 | - Remove RedCarpet header ID patch 133 | - Update language tabs to not disturb existing query strings 134 | 135 | ## Version 1.1 136 | 137 | *July 27, 2014* 138 | 139 | **Fixes:** 140 | 141 | - Finally, a fix for the redcarpet upgrade bug 142 | 143 | ## Version 1.0 144 | 145 | *July 2, 2014* 146 | 147 | [View Issues](https://github.com/tripit/slate/issues?milestone=1&state=closed) 148 | 149 | **Features:** 150 | 151 | - Responsive designs for phones and tablets 152 | - Started tagging versions 153 | 154 | **Fixes:** 155 | 156 | - Fixed 'unrecognized expression' error 157 | - Fixed #undefined hash bug 158 | - Fixed bug where the current language tab would be unselected 159 | - Fixed bug where tocify wouldn't highlight the current section while searching 160 | - Fixed bug where ids of header tags would have special characters that caused problems 161 | - Updated layout so that pages with disabled search wouldn't load search.js 162 | - Cleaned up Javascript 163 | -------------------------------------------------------------------------------- /slate/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@lord.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /slate/Gemfile: -------------------------------------------------------------------------------- 1 | ruby '>=2.3.1' 2 | source 'https://rubygems.org' 3 | 4 | # Middleman 5 | gem 'middleman', '~>4.2.1' 6 | gem 'middleman-syntax', '~> 3.0.0' 7 | gem 'middleman-autoprefixer', '~> 2.7.0' 8 | gem 'middleman-sprockets', '~> 4.1.0' 9 | gem 'middleman-livereload', '~> 3.4.6' 10 | gem 'rouge', '~> 2.0.5' 11 | gem 'redcarpet', '~> 3.4.0' 12 | gem 'nokogiri', '~> 1.8.2' 13 | -------------------------------------------------------------------------------- /slate/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (5.0.1) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | tzinfo (~> 1.1) 9 | addressable (2.5.0) 10 | public_suffix (~> 2.0, >= 2.0.2) 11 | autoprefixer-rails (6.6.1) 12 | execjs 13 | backports (3.6.8) 14 | coffee-script (2.4.1) 15 | coffee-script-source 16 | execjs 17 | coffee-script-source (1.12.2) 18 | compass-import-once (1.0.5) 19 | sass (>= 3.2, < 3.5) 20 | concurrent-ruby (1.0.5) 21 | contracts (0.13.0) 22 | dotenv (2.2.0) 23 | em-websocket (0.5.1) 24 | eventmachine (>= 0.12.9) 25 | http_parser.rb (~> 0.6.0) 26 | erubis (2.7.0) 27 | eventmachine (1.2.7) 28 | execjs (2.7.0) 29 | fast_blank (1.0.0) 30 | fastimage (2.0.1) 31 | addressable (~> 2) 32 | ffi (1.9.25) 33 | haml (5.1.2) 34 | temple (>= 0.8.0) 35 | tilt 36 | hamster (3.0.0) 37 | concurrent-ruby (~> 1.0) 38 | hashie (3.5.1) 39 | http_parser.rb (0.6.0) 40 | i18n (0.7.0) 41 | kramdown (1.13.2) 42 | listen (3.0.8) 43 | rb-fsevent (~> 0.9, >= 0.9.4) 44 | rb-inotify (~> 0.9, >= 0.9.7) 45 | memoist (0.15.0) 46 | middleman (4.2.1) 47 | coffee-script (~> 2.2) 48 | compass-import-once (= 1.0.5) 49 | haml (>= 4.0.5) 50 | kramdown (~> 1.2) 51 | middleman-cli (= 4.2.1) 52 | middleman-core (= 4.2.1) 53 | sass (>= 3.4.0, < 4.0) 54 | middleman-autoprefixer (2.7.1) 55 | autoprefixer-rails (>= 6.5.2, < 7.0.0) 56 | middleman-core (>= 3.3.3) 57 | middleman-cli (4.2.1) 58 | thor (>= 0.17.0, < 2.0) 59 | middleman-core (4.2.1) 60 | activesupport (>= 4.2, < 5.1) 61 | addressable (~> 2.3) 62 | backports (~> 3.6) 63 | bundler (~> 1.1) 64 | contracts (~> 0.13.0) 65 | dotenv 66 | erubis 67 | execjs (~> 2.0) 68 | fast_blank 69 | fastimage (~> 2.0) 70 | hamster (~> 3.0) 71 | hashie (~> 3.4) 72 | i18n (~> 0.7.0) 73 | listen (~> 3.0.0) 74 | memoist (~> 0.14) 75 | padrino-helpers (~> 0.13.0) 76 | parallel 77 | rack (>= 1.4.5, < 3) 78 | sass (>= 3.4) 79 | servolux 80 | tilt (~> 2.0) 81 | uglifier (~> 3.0) 82 | middleman-livereload (3.4.6) 83 | em-websocket (~> 0.5.1) 84 | middleman-core (>= 3.3) 85 | rack-livereload (~> 0.3.15) 86 | middleman-sprockets (4.1.0) 87 | middleman-core (~> 4.0) 88 | sprockets (>= 3.0) 89 | middleman-syntax (3.0.0) 90 | middleman-core (>= 3.2) 91 | rouge (~> 2.0) 92 | mini_portile2 (2.3.0) 93 | minitest (5.10.1) 94 | nokogiri (1.8.2) 95 | mini_portile2 (~> 2.3.0) 96 | padrino-helpers (0.13.3.3) 97 | i18n (~> 0.6, >= 0.6.7) 98 | padrino-support (= 0.13.3.3) 99 | tilt (>= 1.4.1, < 3) 100 | padrino-support (0.13.3.3) 101 | activesupport (>= 3.1) 102 | parallel (1.10.0) 103 | public_suffix (2.0.5) 104 | rack (2.0.5) 105 | rack-livereload (0.3.17) 106 | rack 107 | rb-fsevent (0.9.8) 108 | rb-inotify (0.9.8) 109 | ffi (>= 0.5.0) 110 | redcarpet (3.4.0) 111 | rouge (2.0.7) 112 | sass (3.4.23) 113 | servolux (0.12.0) 114 | sprockets (3.7.2) 115 | concurrent-ruby (~> 1.0) 116 | rack (> 1, < 3) 117 | temple (0.8.2) 118 | thor (0.19.4) 119 | thread_safe (0.3.5) 120 | tilt (2.0.10) 121 | tzinfo (1.2.2) 122 | thread_safe (~> 0.1) 123 | uglifier (3.0.4) 124 | execjs (>= 0.3.0, < 3) 125 | 126 | PLATFORMS 127 | ruby 128 | 129 | DEPENDENCIES 130 | middleman (~> 4.2.1) 131 | middleman-autoprefixer (~> 2.7.0) 132 | middleman-livereload (~> 3.4.6) 133 | middleman-sprockets (~> 4.1.0) 134 | middleman-syntax (~> 3.0.0) 135 | nokogiri (~> 1.8.2) 136 | redcarpet (~> 3.4.0) 137 | rouge (~> 2.0.5) 138 | 139 | RUBY VERSION 140 | ruby 2.3.3p222 141 | 142 | BUNDLED WITH 143 | 1.16.5 144 | -------------------------------------------------------------------------------- /slate/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2008-2013 Concur Technologies, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | not use this file except in compliance with the License. You may obtain 5 | a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | License for the specific language governing permissions and limitations 13 | under the License. -------------------------------------------------------------------------------- /slate/README.md: -------------------------------------------------------------------------------- 1 |

2 | Slate: API Documentation Generator 3 |
4 | Build Status 5 |

6 | 7 |

Slate helps you create beautiful, intelligent, responsive API documentation.

8 | 9 |

Screenshot of Example Documentation created with Slate

10 | 11 |

The example above was created with Slate. Check it out at lord.github.io/slate.

12 | 13 | Features 14 | ------------ 15 | 16 | * **Clean, intuitive design** — With Slate, the description of your API is on the left side of your documentation, and all the code examples are on the right side. Inspired by [Stripe's](https://stripe.com/docs/api) and [PayPal's](https://developer.paypal.com/webapps/developer/docs/api/) API docs. Slate is responsive, so it looks great on tablets, phones, and even in print. 17 | 18 | * **Everything on a single page** — Gone are the days when your users had to search through a million pages to find what they wanted. Slate puts the entire documentation on a single page. We haven't sacrificed linkability, though. As you scroll, your browser's hash will update to the nearest header, so linking to a particular point in the documentation is still natural and easy. 19 | 20 | * **Slate is just Markdown** — When you write docs with Slate, you're just writing Markdown, which makes it simple to edit and understand. Everything is written in Markdown — even the code samples are just Markdown code blocks. 21 | 22 | * **Write code samples in multiple languages** — If your API has bindings in multiple programming languages, you can easily put in tabs to switch between them. In your document, you'll distinguish different languages by specifying the language name at the top of each code block, just like with GitHub Flavored Markdown. 23 | 24 | * **Out-of-the-box syntax highlighting** for [over 100 languages](https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers), no configuration required. 25 | 26 | * **Automatic, smoothly scrolling table of contents** on the far left of the page. As you scroll, it displays your current position in the document. It's fast, too. We're using Slate at TripIt to build documentation for our new API, where our table of contents has over 180 entries. We've made sure that the performance remains excellent, even for larger documents. 27 | 28 | * **Let your users update your documentation for you** — By default, your Slate-generated documentation is hosted in a public GitHub repository. Not only does this mean you get free hosting for your docs with GitHub Pages, but it also makes it simple for other developers to make pull requests to your docs if they find typos or other problems. Of course, if you don't want to use GitHub, you're also welcome to host your docs elsewhere. 29 | 30 | * **RTL Support** Full right-to-left layout for RTL languages such as Arabic, Persian (Farsi), Hebrew etc. 31 | 32 | Getting started with Slate is super easy! Simply fork this repository and follow the instructions below. Or, if you'd like to check out what Slate is capable of, take a look at the [sample docs](http://lord.github.io/slate). 33 | 34 | Getting Started with Slate 35 | ------------------------------ 36 | 37 | ### Prerequisites 38 | 39 | You're going to need: 40 | 41 | - **Linux or macOS** — Windows may work, but is unsupported. 42 | - **Ruby, version 2.3.1 or newer** 43 | - **Bundler** — If Ruby is already installed, but the `bundle` command doesn't work, just run `gem install bundler` in a terminal. 44 | 45 | ### Getting Set Up 46 | 47 | 1. Fork this repository on GitHub. 48 | 2. Clone *your forked repository* (not our original one) to your hard drive with `git clone https://github.com/YOURUSERNAME/slate.git` 49 | 3. `cd slate` 50 | 4. Initialize and start Slate. You can either do this locally, or with Vagrant: 51 | 52 | ```shell 53 | # either run this to run locally 54 | bundle install 55 | bundle exec middleman server 56 | 57 | # OR run this to run with vagrant 58 | vagrant up 59 | ``` 60 | 61 | You can now see the docs at http://localhost:4567. Whoa! That was fast! 62 | 63 | Now that Slate is all set up on your machine, you'll probably want to learn more about [editing Slate markdown](https://github.com/lord/slate/wiki/Markdown-Syntax), or [how to publish your docs](https://github.com/lord/slate/wiki/Deploying-Slate). 64 | 65 | If you'd prefer to use Docker, instructions are available [in the wiki](https://github.com/lord/slate/wiki/Docker). 66 | 67 | ### Note on JavaScript Runtime 68 | 69 | For those who don't have JavaScript runtime or are experiencing JavaScript runtime issues with ExecJS, it is recommended to add the [rubyracer gem](https://github.com/cowboyd/therubyracer) to your gemfile and run `bundle` again. 70 | 71 | Companies Using Slate 72 | --------------------------------- 73 | 74 | * [NASA](https://api.nasa.gov) 75 | * [Sony](http://developers.cimediacloud.com) 76 | * [Best Buy](https://bestbuyapis.github.io/api-documentation/) 77 | * [Travis-CI](https://docs.travis-ci.com/api/) 78 | * [Greenhouse](https://developers.greenhouse.io/harvest.html) 79 | * [Woocommerce](http://woocommerce.github.io/woocommerce-rest-api-docs/) 80 | * [Dwolla](https://docs.dwolla.com/) 81 | * [Clearbit](https://clearbit.com/docs) 82 | * [Coinbase](https://developers.coinbase.com/api) 83 | * [Parrot Drones](http://developer.parrot.com/docs/bebop/) 84 | * [Scale](https://docs.scaleapi.com/) 85 | 86 | You can view more in [the list on the wiki](https://github.com/lord/slate/wiki/Slate-in-the-Wild). 87 | 88 | Questions? Need Help? Found a bug? 89 | -------------------- 90 | 91 | If you've got questions about setup, deploying, special feature implementation in your fork, or just want to chat with the developer, please feel free to [start a thread in our Spectrum community](https://spectrum.chat/slate)! 92 | 93 | Found a bug with upstream Slate? Go ahead and [submit an issue](https://github.com/lord/slate/issues). And, of course, feel free to submit pull requests with bug fixes or changes to the `dev` branch. 94 | 95 | Contributors 96 | -------------------- 97 | 98 | Slate was built by [Robert Lord](https://lord.io) while interning at [TripIt](https://www.tripit.com/). 99 | 100 | Thanks to the following people who have submitted major pull requests: 101 | 102 | - [@chrissrogers](https://github.com/chrissrogers) 103 | - [@bootstraponline](https://github.com/bootstraponline) 104 | - [@realityking](https://github.com/realityking) 105 | - [@cvkef](https://github.com/cvkef) 106 | 107 | Also, thanks to [Sauce Labs](http://saucelabs.com) for sponsoring the development of the responsive styles. 108 | 109 | Special Thanks 110 | -------------------- 111 | - [Middleman](https://github.com/middleman/middleman) 112 | - [jquery.tocify.js](https://github.com/gfranko/jquery.tocify.js) 113 | - [middleman-syntax](https://github.com/middleman/middleman-syntax) 114 | - [middleman-gh-pages](https://github.com/edgecase/middleman-gh-pages) 115 | - [Font Awesome](http://fortawesome.github.io/Font-Awesome/) 116 | -------------------------------------------------------------------------------- /slate/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | config.vm.box = "ubuntu/trusty64" 3 | config.vm.network :forwarded_port, guest: 4567, host: 4567 4 | config.vm.provider "virtualbox" do |vb| 5 | vb.memory = "2048" 6 | end 7 | 8 | config.vm.provision "bootstrap", 9 | type: "shell", 10 | inline: <<-SHELL 11 | sudo apt-add-repository ppa:brightbox/ruby-ng 12 | sudo apt-get update 13 | sudo apt-get install -yq ruby2.4 ruby2.4-dev 14 | sudo apt-get install -yq pkg-config build-essential nodejs git libxml2-dev libxslt-dev 15 | sudo apt-get autoremove -yq 16 | gem2.4 install --no-ri --no-rdoc bundler 17 | SHELL 18 | 19 | # add the local user git config to the vm 20 | config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig" 21 | 22 | config.vm.provision "install", 23 | type: "shell", 24 | privileged: false, 25 | inline: <<-SHELL 26 | echo "==============================================" 27 | echo "Installing app dependencies" 28 | cd /vagrant 29 | bundle config build.nokogiri --use-system-libraries 30 | bundle install 31 | SHELL 32 | 33 | config.vm.provision "run", 34 | type: "shell", 35 | privileged: false, 36 | run: "always", 37 | inline: <<-SHELL 38 | echo "==============================================" 39 | echo "Starting up middleman at http://localhost:4567" 40 | echo "If it does not come up, check the ~/middleman.log file for any error messages" 41 | cd /vagrant 42 | bundle exec middleman server --watcher-force-polling --watcher-latency=1 &> ~/middleman.log & 43 | SHELL 44 | end 45 | -------------------------------------------------------------------------------- /slate/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | bundle exec middleman build --clean 3 | -------------------------------------------------------------------------------- /slate/config.rb: -------------------------------------------------------------------------------- 1 | # Unique header generation 2 | require './lib/unique_head.rb' 3 | 4 | # Markdown 5 | set :markdown_engine, :redcarpet 6 | set :markdown, 7 | fenced_code_blocks: true, 8 | smartypants: true, 9 | disable_indented_code_blocks: true, 10 | prettify: true, 11 | strikethrough: true, 12 | tables: true, 13 | with_toc_data: true, 14 | no_intra_emphasis: true, 15 | renderer: UniqueHeadCounter 16 | 17 | # Assets 18 | set :css_dir, 'stylesheets' 19 | set :js_dir, 'javascripts' 20 | set :images_dir, 'images' 21 | set :fonts_dir, 'fonts' 22 | set :build_dir, '../docs' 23 | 24 | # Activate the syntax highlighter 25 | activate :syntax 26 | ready do 27 | require './lib/multilang.rb' 28 | end 29 | 30 | activate :sprockets 31 | 32 | activate :autoprefixer do |config| 33 | config.browsers = ['last 2 version', 'Firefox ESR'] 34 | config.cascade = false 35 | config.inline = true 36 | end 37 | 38 | # Github pages require relative links 39 | activate :relative_assets 40 | set :relative_links, true 41 | 42 | # Build Configuration 43 | configure :build do 44 | # If you're having trouble with Middleman hanging, commenting 45 | # out the following two lines has been known to help 46 | activate :minify_css 47 | activate :minify_javascript 48 | # activate :relative_assets 49 | # activate :asset_hash 50 | # activate :gzip 51 | end 52 | 53 | # Deploy Configuration 54 | # If you want Middleman to listen on a different port, you can set that below 55 | set :port, 4567 56 | activate :livereload 57 | 58 | helpers do 59 | require './lib/toc_data.rb' 60 | end 61 | -------------------------------------------------------------------------------- /slate/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit #abort if any command fails 3 | me=$(basename "$0") 4 | 5 | help_message="\ 6 | Usage: $me [-c FILE] [] 7 | Deploy generated files to a git branch. 8 | 9 | Options: 10 | 11 | -h, --help Show this help information. 12 | -v, --verbose Increase verbosity. Useful for debugging. 13 | -e, --allow-empty Allow deployment of an empty directory. 14 | -m, --message MESSAGE Specify the message used when committing on the 15 | deploy branch. 16 | -n, --no-hash Don't append the source commit's hash to the deploy 17 | commit's message. 18 | --source-only Only build but not push 19 | --push-only Only push but not build 20 | " 21 | 22 | 23 | run_build() { 24 | bundle exec middleman build --clean 25 | } 26 | 27 | parse_args() { 28 | # Set args from a local environment file. 29 | if [ -e ".env" ]; then 30 | source .env 31 | fi 32 | 33 | # Parse arg flags 34 | # If something is exposed as an environment variable, set/overwrite it 35 | # here. Otherwise, set/overwrite the internal variable instead. 36 | while : ; do 37 | if [[ $1 = "-h" || $1 = "--help" ]]; then 38 | echo "$help_message" 39 | return 0 40 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then 41 | verbose=true 42 | shift 43 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then 44 | allow_empty=true 45 | shift 46 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then 47 | commit_message=$2 48 | shift 2 49 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then 50 | GIT_DEPLOY_APPEND_HASH=false 51 | shift 52 | else 53 | break 54 | fi 55 | done 56 | 57 | # Set internal option vars from the environment and arg flags. All internal 58 | # vars should be declared here, with sane defaults if applicable. 59 | 60 | # Source directory & target branch. 61 | deploy_directory=build 62 | deploy_branch=gh-pages 63 | 64 | #if no user identity is already set in the current git environment, use this: 65 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh} 66 | default_email=${GIT_DEPLOY_EMAIL:-} 67 | 68 | #repository to deploy to. must be readable and writable. 69 | repo=origin 70 | 71 | #append commit hash to the end of message by default 72 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true} 73 | } 74 | 75 | main() { 76 | parse_args "$@" 77 | 78 | enable_expanded_output 79 | 80 | if ! git diff --exit-code --quiet --cached; then 81 | echo Aborting due to uncommitted changes in the index >&2 82 | return 1 83 | fi 84 | 85 | commit_title=`git log -n 1 --format="%s" HEAD` 86 | commit_hash=` git log -n 1 --format="%H" HEAD` 87 | 88 | #default commit message uses last title if a custom one is not supplied 89 | if [[ -z $commit_message ]]; then 90 | commit_message="publish: $commit_title" 91 | fi 92 | 93 | #append hash to commit message unless no hash flag was found 94 | if [ $append_hash = true ]; then 95 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash" 96 | fi 97 | 98 | previous_branch=`git rev-parse --abbrev-ref HEAD` 99 | 100 | if [ ! -d "$deploy_directory" ]; then 101 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2 102 | return 1 103 | fi 104 | 105 | # must use short form of flag in ls for compatibility with macOS and BSD 106 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then 107 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2 108 | return 1 109 | fi 110 | 111 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then 112 | # deploy_branch exists in $repo; make sure we have the latest version 113 | 114 | disable_expanded_output 115 | git fetch --force $repo $deploy_branch:$deploy_branch 116 | enable_expanded_output 117 | fi 118 | 119 | # check if deploy_branch exists locally 120 | if git show-ref --verify --quiet "refs/heads/$deploy_branch" 121 | then incremental_deploy 122 | else initial_deploy 123 | fi 124 | 125 | restore_head 126 | } 127 | 128 | initial_deploy() { 129 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch 130 | git --work-tree "$deploy_directory" add --all 131 | commit+push 132 | } 133 | 134 | incremental_deploy() { 135 | #make deploy_branch the current branch 136 | git symbolic-ref HEAD refs/heads/$deploy_branch 137 | #put the previously committed contents of deploy_branch into the index 138 | git --work-tree "$deploy_directory" reset --mixed --quiet 139 | git --work-tree "$deploy_directory" add --all 140 | 141 | set +o errexit 142 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$? 143 | set -o errexit 144 | case $diff in 145 | 0) echo No changes to files in $deploy_directory. Skipping commit.;; 146 | 1) commit+push;; 147 | *) 148 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to master, use: git symbolic-ref HEAD refs/heads/master && git reset --mixed >&2 149 | return $diff 150 | ;; 151 | esac 152 | } 153 | 154 | commit+push() { 155 | set_user_id 156 | git --work-tree "$deploy_directory" commit -m "$commit_message" 157 | 158 | disable_expanded_output 159 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token 160 | git push --quiet $repo $deploy_branch 161 | enable_expanded_output 162 | } 163 | 164 | #echo expanded commands as they are executed (for debugging) 165 | enable_expanded_output() { 166 | if [ $verbose ]; then 167 | set -o xtrace 168 | set +o verbose 169 | fi 170 | } 171 | 172 | #this is used to avoid outputting the repo URL, which may contain a secret token 173 | disable_expanded_output() { 174 | if [ $verbose ]; then 175 | set +o xtrace 176 | set -o verbose 177 | fi 178 | } 179 | 180 | set_user_id() { 181 | if [[ -z `git config user.name` ]]; then 182 | git config user.name "$default_username" 183 | fi 184 | if [[ -z `git config user.email` ]]; then 185 | git config user.email "$default_email" 186 | fi 187 | } 188 | 189 | restore_head() { 190 | if [[ $previous_branch = "HEAD" ]]; then 191 | #we weren't on any branch before, so just set HEAD back to the commit it was on 192 | git update-ref --no-deref HEAD $commit_hash $deploy_branch 193 | else 194 | git symbolic-ref HEAD refs/heads/$previous_branch 195 | fi 196 | 197 | git reset --mixed 198 | } 199 | 200 | filter() { 201 | sed -e "s|$repo|\$repo|g" 202 | } 203 | 204 | sanitize() { 205 | "$@" 2> >(filter 1>&2) | filter 206 | } 207 | 208 | if [[ $1 = --source-only ]]; then 209 | run_build 210 | elif [[ $1 = --push-only ]]; then 211 | main "$@" 212 | else 213 | run_build 214 | main "$@" 215 | fi 216 | -------------------------------------------------------------------------------- /slate/font-selection.json: -------------------------------------------------------------------------------- 1 | { 2 | "IcoMoonType": "selection", 3 | "icons": [ 4 | { 5 | "icon": { 6 | "paths": [ 7 | "M438.857 73.143q119.429 0 220.286 58.857t159.714 159.714 58.857 220.286-58.857 220.286-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857zM512 785.714v-108.571q0-8-5.143-13.429t-12.571-5.429h-109.714q-7.429 0-13.143 5.714t-5.714 13.143v108.571q0 7.429 5.714 13.143t13.143 5.714h109.714q7.429 0 12.571-5.429t5.143-13.429zM510.857 589.143l10.286-354.857q0-6.857-5.714-10.286-5.714-4.571-13.714-4.571h-125.714q-8 0-13.714 4.571-5.714 3.429-5.714 10.286l9.714 354.857q0 5.714 5.714 10t13.714 4.286h105.714q8 0 13.429-4.286t6-10z" 8 | ], 9 | "attrs": [], 10 | "isMulticolor": false, 11 | "tags": [ 12 | "exclamation-circle" 13 | ], 14 | "defaultCode": 61546, 15 | "grid": 14 16 | }, 17 | "attrs": [], 18 | "properties": { 19 | "id": 100, 20 | "order": 4, 21 | "prevSize": 28, 22 | "code": 58880, 23 | "name": "exclamation-sign", 24 | "ligatures": "" 25 | }, 26 | "setIdx": 0, 27 | "iconIdx": 0 28 | }, 29 | { 30 | "icon": { 31 | "paths": [ 32 | "M585.143 786.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-54.857v-292.571q0-8-5.143-13.143t-13.143-5.143h-182.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h54.857v182.857h-54.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h256q8 0 13.143-5.143t5.143-13.143zM512 274.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-109.714q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h109.714q8 0 13.143-5.143t5.143-13.143zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z" 33 | ], 34 | "attrs": [], 35 | "isMulticolor": false, 36 | "tags": [ 37 | "info-circle" 38 | ], 39 | "defaultCode": 61530, 40 | "grid": 14 41 | }, 42 | "attrs": [], 43 | "properties": { 44 | "id": 85, 45 | "order": 3, 46 | "name": "info-sign", 47 | "prevSize": 28, 48 | "code": 58882 49 | }, 50 | "setIdx": 0, 51 | "iconIdx": 2 52 | }, 53 | { 54 | "icon": { 55 | "paths": [ 56 | "M733.714 419.429q0-16-10.286-26.286l-52-51.429q-10.857-10.857-25.714-10.857t-25.714 10.857l-233.143 232.571-129.143-129.143q-10.857-10.857-25.714-10.857t-25.714 10.857l-52 51.429q-10.286 10.286-10.286 26.286 0 15.429 10.286 25.714l206.857 206.857q10.857 10.857 25.714 10.857 15.429 0 26.286-10.857l310.286-310.286q10.286-10.286 10.286-25.714zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z" 57 | ], 58 | "attrs": [], 59 | "isMulticolor": false, 60 | "tags": [ 61 | "check-circle" 62 | ], 63 | "defaultCode": 61528, 64 | "grid": 14 65 | }, 66 | "attrs": [], 67 | "properties": { 68 | "id": 83, 69 | "order": 9, 70 | "prevSize": 28, 71 | "code": 58886, 72 | "name": "ok-sign" 73 | }, 74 | "setIdx": 0, 75 | "iconIdx": 6 76 | }, 77 | { 78 | "icon": { 79 | "paths": [ 80 | "M658.286 475.429q0-105.714-75.143-180.857t-180.857-75.143-180.857 75.143-75.143 180.857 75.143 180.857 180.857 75.143 180.857-75.143 75.143-180.857zM950.857 950.857q0 29.714-21.714 51.429t-51.429 21.714q-30.857 0-51.429-21.714l-196-195.429q-102.286 70.857-228 70.857-81.714 0-156.286-31.714t-128.571-85.714-85.714-128.571-31.714-156.286 31.714-156.286 85.714-128.571 128.571-85.714 156.286-31.714 156.286 31.714 128.571 85.714 85.714 128.571 31.714 156.286q0 125.714-70.857 228l196 196q21.143 21.143 21.143 51.429z" 81 | ], 82 | "width": 951, 83 | "attrs": [], 84 | "isMulticolor": false, 85 | "tags": [ 86 | "search" 87 | ], 88 | "defaultCode": 61442, 89 | "grid": 14 90 | }, 91 | "attrs": [], 92 | "properties": { 93 | "id": 2, 94 | "order": 1, 95 | "prevSize": 28, 96 | "code": 58887, 97 | "name": "icon-search" 98 | }, 99 | "setIdx": 0, 100 | "iconIdx": 7 101 | } 102 | ], 103 | "height": 1024, 104 | "metadata": { 105 | "name": "slate", 106 | "license": "SIL OFL 1.1" 107 | }, 108 | "preferences": { 109 | "showGlyphs": true, 110 | "showQuickUse": true, 111 | "showQuickUse2": true, 112 | "showSVGs": true, 113 | "fontPref": { 114 | "prefix": "icon-", 115 | "metadata": { 116 | "fontFamily": "slate", 117 | "majorVersion": 1, 118 | "minorVersion": 0, 119 | "description": "Based on FontAwesome", 120 | "license": "SIL OFL 1.1" 121 | }, 122 | "metrics": { 123 | "emSize": 1024, 124 | "baseline": 6.25, 125 | "whitespace": 50 126 | }, 127 | "resetPoint": 58880, 128 | "showSelector": false, 129 | "selector": "class", 130 | "classSelector": ".icon", 131 | "showMetrics": false, 132 | "showMetadata": true, 133 | "showVersion": true, 134 | "ie7": false 135 | }, 136 | "imagePref": { 137 | "prefix": "icon-", 138 | "png": true, 139 | "useClassSelector": true, 140 | "color": 4473924, 141 | "bgColor": 16777215 142 | }, 143 | "historySize": 100, 144 | "showCodes": true, 145 | "gridSize": 16, 146 | "showLiga": false 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /slate/lib/multilang.rb: -------------------------------------------------------------------------------- 1 | module Multilang 2 | def block_code(code, full_lang_name) 3 | if full_lang_name 4 | parts = full_lang_name.split('--') 5 | rouge_lang_name = (parts) ? parts[0] : "" # just parts[0] here causes null ref exception when no language specified 6 | super(code, rouge_lang_name).sub("highlight #{rouge_lang_name}") do |match| 7 | match + " tab-" + full_lang_name 8 | end 9 | else 10 | super(code, full_lang_name) 11 | end 12 | end 13 | end 14 | 15 | require 'middleman-core/renderers/redcarpet' 16 | Middleman::Renderers::MiddlemanRedcarpetHTML.send :include, Multilang 17 | -------------------------------------------------------------------------------- /slate/lib/nesting_unique_head.rb: -------------------------------------------------------------------------------- 1 | # Nested unique header generation 2 | require 'middleman-core/renderers/redcarpet' 3 | 4 | class NestingUniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML 5 | def initialize 6 | super 7 | @@headers_history = {} if !defined?(@@headers_history) 8 | end 9 | 10 | def header(text, header_level) 11 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize 12 | @@headers_history[header_level] = text.parameterize 13 | 14 | if header_level > 1 15 | for i in (header_level - 1).downto(1) 16 | friendly_text.prepend("#{@@headers_history[i]}-") if @@headers_history.key?(i) 17 | end 18 | end 19 | 20 | return "#{text}" 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /slate/lib/toc_data.rb: -------------------------------------------------------------------------------- 1 | require 'nokogiri' 2 | 3 | def toc_data(page_content) 4 | html_doc = Nokogiri::HTML::DocumentFragment.parse(page_content) 5 | 6 | # get a flat list of headers 7 | headers = [] 8 | html_doc.css('h1, h2, h3').each do |header| 9 | headers.push({ 10 | id: header.attribute('id').to_s, 11 | content: header.children, 12 | title: header.children.to_s.gsub(/<[^>]*>/, ''), 13 | level: header.name[1].to_i, 14 | children: [] 15 | }) 16 | end 17 | 18 | [3,2].each do |header_level| 19 | header_to_nest = nil 20 | headers = headers.reject do |header| 21 | if header[:level] == header_level 22 | header_to_nest[:children].push header if header_to_nest 23 | true 24 | else 25 | header_to_nest = header if header[:level] < header_level 26 | false 27 | end 28 | end 29 | end 30 | headers 31 | end 32 | -------------------------------------------------------------------------------- /slate/lib/unique_head.rb: -------------------------------------------------------------------------------- 1 | # Unique header generation 2 | require 'middleman-core/renderers/redcarpet' 3 | require 'digest' 4 | class UniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML 5 | def initialize 6 | super 7 | @head_count = {} 8 | end 9 | def header(text, header_level) 10 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize 11 | if friendly_text.strip.length == 0 12 | # Looks like parameterize removed the whole thing! It removes many unicode 13 | # characters like Chinese and Russian. To get a unique URL, let's just 14 | # URI escape the whole header 15 | friendly_text = Digest::SHA1.hexdigest(text)[0,10] 16 | end 17 | @head_count[friendly_text] ||= 0 18 | @head_count[friendly_text] += 1 19 | if @head_count[friendly_text] > 1 20 | friendly_text += "-#{@head_count[friendly_text]}" 21 | end 22 | return "#{text}" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /slate/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | bundle exec middleman server 3 | -------------------------------------------------------------------------------- /slate/source/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/fonts/slate.eot -------------------------------------------------------------------------------- /slate/source/fonts/slate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /slate/source/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/fonts/slate.ttf -------------------------------------------------------------------------------- /slate/source/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/fonts/slate.woff -------------------------------------------------------------------------------- /slate/source/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/fonts/slate.woff2 -------------------------------------------------------------------------------- /slate/source/images/clientCredentialsSequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/clientCredentialsSequence.png -------------------------------------------------------------------------------- /slate/source/images/holderDomain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/holderDomain.png -------------------------------------------------------------------------------- /slate/source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/logo.png -------------------------------------------------------------------------------- /slate/source/images/logoSanta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/logoSanta.png -------------------------------------------------------------------------------- /slate/source/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/navbar.png -------------------------------------------------------------------------------- /slate/source/images/redirPartA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/redirPartA.png -------------------------------------------------------------------------------- /slate/source/images/redirPartB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/redirPartB.png -------------------------------------------------------------------------------- /slate/source/images/redirPartC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/slate/source/images/redirPartC.png -------------------------------------------------------------------------------- /slate/source/index.html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Consumer Data Right Security Profile 3 | 4 | language_tabs: # must be one of https://git.io/vQNgJ 5 | - http 6 | 7 | toc_footers: 8 | - Consumer Data Standards Home 9 | - CDR InfoSec on GitHub 10 | 11 | search: true 12 | --- 13 | 14 | 20 | 21 | # Introduction 22 | 23 | This Information Security profile has been developed as part of the introduction in Australia of the [Consumer Data Right](https://www.accc.gov.au/focus-areas/consumer-data-right "ACCC Consumer Data Right webpage") legislation to give Australians greater control over their data. 24 | 25 | The Consumer Data Right is intended to apply sector by sector across the whole economy, beginning in the banking, energy and telecommunications sectors. These standards have been developed to facilitate the Consumer Data Right by acting as a specific baseline for implementation. 26 | 27 | These standards are governed by the Consumer Data Standards team inside Data61. Data61 has been appointed as the interim standards body. The work of the team is overseen by Mr. Andrew Stevens as interim Chair, with industry and consumer advice provided by an Advisory Committee. Data61 works closely with the Australian Competition and Consumer Commission (ACCC) as lead regulator of the Consumer Data Right, supported by the Office of the Australian Information Commissioner (OAIC). 28 | 29 | 30 | 37 | 38 | # 1. InfoSec Profile 0.1.1 39 | 40 | 43 | 44 | ## 1.1. History 45 | 46 | | Author | Date | Version | Description | 47 | |-----------------|------------|---------|------------| 48 | | LP | 22/11/2018 | 0.0.1 | Created | 49 | | LP | 30/11/2018 | 0.0.2 | Created | 50 | | LP | 10/12/2018 | 0.0.3 | Created | 51 | | LP | 20/12/2018 | 0.1.0 | Created | 52 | | LP | 07/01/2019 | 0.1.1 | Created | 53 | 54 | The detailed change log for this artifact is available [here](https://github.com/ConsumerDataStandardsAustralia/infosec/blob/master/CHANGELOG.md). 55 | 56 | ## 1.2. Symbols and Abbreviated terms 57 | - **API**: Application Programming Interface 58 | - **CA**: Certificate Authority 59 | - **CDR:** Consumer Data Right 60 | - **CDR-SP**: Consumer Data Right Security Profile 61 | - **CIBA**: Client Initiated Backchannel Authentication 62 | - **CL**: Credential Level 63 | - **DH:** Data Holder 64 | - **DR:** Data Recipient 65 | - **DTA:** Digital Transformation Agency 66 | - **FAPI:** Financial API 67 | - **HoK:** Holder of Key 68 | - **JSON:** The JavaScript Object Notation 69 | - **JWA:** JSON Web Algorithms 70 | - **JWE:** JSON Web Encryption 71 | - **JWK:** JSON Web Key 72 | - **JWKS:** JSON Web Key Set 73 | - **JWS:** JSON Web Signing 74 | - **JWT:** JSON Web Token 75 | - **IP:** Identity Proofing 76 | - **LoA:** Level of Assurance 77 | - **LoAs:** Levels of Assurance 78 | - **MTLS:** Mutual Transport Layer Security 79 | - **OIDC:** Open ID Connect 80 | - **PI:** Personal Information 81 | - **PKI:** Public Key Infrastructure 82 | - **PPID:** Pairwise Pseudonymous Identifier 83 | - **REST:** Representational State Transfer 84 | - **TDIF:** Trusted Digital Identity Framework 85 | - **TLS:** Transport Layer Security 86 | - **VoT:** Vector of Trust 87 | 88 | ## 1.3. Requirements Notation and Conventions 89 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119) **[RFC2119]**. 90 | 91 | # 2. Overview 92 | This artifact details the [Consumer Data Right](https://www.accc.gov.au/focus-areas/consumer-data-right) **[CDR]** Information Security 93 | Profile (CDR-SP). This profile will be built upon the foundations of the 94 | [Financial-grade API Read Write Profile](https://openid.net/specs/openid-financial-api-part-2.html) **[FAPI-RW]**, the [Financial-grade API Client Initiated Backchannel Authentication Profile](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default) **[FAPI-CIBA]**, and other standards relating to 95 | [Open ID Connect 1.0](http://openid.net/specs/openid-connect-core-1_0.html) **[OIDC]**. 96 | 97 | Whilst this is a technical artifact, it is guided by the core principles that 98 | have to led to the creation of the Consumer Data Right. These are: 99 | 100 | - The CDR should be *consumer focussed*. 101 | - The CDR should encourage *competition*. 102 | - The CDR should create *opportunities*. 103 | - The CDR should be *efficient and fair*. 104 | 105 | # 3. CDR Federation 106 | The CDR Federation will facilitate the secure exchange of consumer data and federation metadata between 107 | multiple system entities which will assume one or more of the following roles: 108 | 109 | - **Data Holder**: 110 | - Multiple Data Holders will be supported. 111 | - **Data Recipient**: 112 | - Multiple Data Recipients will be supported. 113 | - **Registry**: 114 | - It is envisaged that only one registry will be supported and will be 115 | maintained by the Australian Competition and Consumer Commission (ACCC). 116 | 117 | ## 3.1. Data Holder 118 | The Data Holder (DH) is a system entity that authenticates a consumer 119 | (resource owner or user), as part of an authorisation process initiated by a Data 120 | Recipient, and issues an authorisation for that Data Recipient to access the consumer's data via published APIs. 121 | 122 | A Data Holder assumes the role of an **[OIDC]** [OpenID Provider](https://openid.net/specs/openid-connect-core-1_0.html#Overview). 123 | 124 | ## 3.2. Data Recipient 125 | A Data Recipient (DR) is system entity that is authorised by a 126 | Data Holder to access consumer resources (APIs). A Data Recipient MUST capture consumer consent prior to commencing an authorisation process with a Data Holder. 127 | 128 | A Data Recipient MUST be accredited in order to participate in the CDR Federation. Accreditation rules for Data Recipients are beyond the scope of this artifact. 129 | 130 | A Data Recipient assumes the role of an **[OIDC]** [Relying Party (Client)](https://openid.net/specs/openid-connect-core-1_0.html#Overview). 131 | 132 | ## 3.3. Registry 133 | 136 | 137 | The Registry is a central point of discovery for both Data Holders and Data 138 | Recipients. Data Holders and Data Recipients must be created as entities in the Registry in order for them to participate as members of the CDR Federation. The functionality of the Registry will include but will not be limited to: 139 | 140 | - **Management of Identities and Access**: The Registry will allow registered persons, on behalf of Data Holders and Data Recipients, to manage the metadata of their associated organisations and systems. 141 | - **Management of Certificates**: The Registry will facilitate the issuing, management and revocation of digital certificates. 142 | - **Discoverability and Search**: The Registry will expose APIs and GUIs (Web applications) in order to support metadata queries across Registry entities. 143 | 144 | A full description of the Registry is beyond the scope of this document. 145 | 146 | # 4. Authentication Flows 147 | This profile supports the authentication flows specified by [FAPI](https://openid.net/wg/fapi/) **[FAPI]**. These are: 148 | 149 | - The Hybrid Flow outlined at [section 3.3](https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth) of **[OIDC]**. 150 | - This MUST be supported by Data Holders. 151 | - The Client Initiated Backchannel Authentication flow outlined under the [FAPI CIBA profile](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default) **[FAPI-CIBA]**. 152 | - This MAY be supported by Data Holders. 153 | 154 | 155 | ## 4.1. OIDC Hybrid Flow 156 | The **[OIDC]** Hybrid Flow is a type of redirection flow where the consumers user 157 | agent is redirected from a Data Recipient’s (Relying Party) web site to a Data 158 | Holder’s Authorisation endpoint in the context of an **[OIDC]** authentication 159 | request. The Hybrid flow incorporates aspects of the both the implicit flow and 160 | authorisation code flow detailed under **[OIDC]**. 161 | 162 | Only a `response_type` (see [section 3](https://openid.net/specs/openid-connect-core-1_0.html#Authentication) of **[OIDC]**) of `code id_token` SHALL be allowed. 163 | 164 | The `request_uri` parameter SHALL NOT be supported. 165 | 166 | 167 | ## 4.2. Client-Initiated Backchannel Authentication (CIBA) 168 | Client Initiated Backchannel Authentication (CIBA) enables a Data Recipient (Client) to 169 | initiate the authentication of an end-user at a Data Holder (OpenID Provider) by means of decoupled or out-band 170 | mechanisms **[FAPI-CIBA]**. 171 | 172 | Authorisation server rules for **[FAPI-CIBA]** are covered under [section 5.2.2 of the FAPI CIBA profile](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default#markdown-header-522-authorization-server). 173 | 174 | Login hints MUST not reveal Personal Information (PI) about the consumer or end-user. 175 | 176 | Client rules for **[FAPI-CIBA]** are outlined under [section 5.2.3 of the FAPI CIBA profile](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default#markdown-header-523-confidential-client). 177 | 178 | 179 | # 5. Client Authentication 180 | Data Holder's MUST support the `private_key_jwt` Client Authentication method specified at [section 9](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) of **[OIDC]**. 181 | 182 | The PKI Mutual TLS OAuth Client Authentication Method SHALL not be supported. However as specified under [section 11.2](#mutual-tls), all back-channel communication between Data Recipient and Data Holder systems MUST incorporate, unless stated otherwise, MTLS as part of the TLS handshake. 183 | 184 | ## 5.1. private\_key\_jwt 185 | 186 | 187 | > Non-Normative Example 188 | 189 | ``` 190 | POST /token HTTP/1.1 191 | Host: www.holder.com.au 192 | Content-Type: application/x-www-form-urlencoded 193 | 194 | grant_type=authorization_code& 195 | code=i1WsRn1uB1& 196 | client_id=s6BhdRkqt3& 197 | client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer& 198 | client_assertion=eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyNDU2In0.ey ... 199 | 200 | # Decoded client assertion JWT 201 | { 202 | "alg": "PS256", 203 | "typ": "JWT", 204 | "kid": "12456" 205 | } 206 | { 207 | "iss": "12345", 208 | "sub": "12345", 209 | "iat": 1516239022, 210 | "exp": 1516239322, 211 | "aud": "https://www.holder.com.au/token", 212 | "jti": "37747cd1-c105-4569-9f75-4adf28b73e31" 213 | } 214 | ``` 215 | 216 | The `private_key_jwt` authentication method is enabled through the delivery of an encoded **[JWT]** signed using the Data Recipient's private key and thus facilitates non-repudiation. The **[JWT]** represents an assertion that MUST include the following claims: 217 | 218 | - `iss`: The client ID of the bearer. 219 | - `sub`: The client ID of the bearer. 220 | - `aud`: The URL of the endpoint being invoked. 221 | - `exp`: A JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC expiry time. 222 | - `jti`: A unique identifier generated by the client for this authentication. 223 | 224 | The following claims MAY be included: 225 | 226 | - `iat`: A JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC issued at time. 227 | 228 | When invoking a protected endpoint, the aforementioned assertion MUST be sent with the `POST` method and MUST include the following parameters: 229 | 230 | - `grant_type`: This parameter MUST only be included when invoking the Token Endpoint and MUST be set to `authorisation_code` or `client_credentials`. 231 | - `code`: This parameter MUST only be included when invoking the Token Endpoint after utilising the [Hybrid Authentication flow](#hybrid-flow). This is the value of the code parameter returned in the authorisation response. 232 | - `client_id`: The ID of the calling Client. 233 | - `client_assertion_type`: This MUST be set to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. 234 | - `client_assertion`: The encoded assertion JWT. 235 | 236 | # 6. OIDC Client Types 237 | Only Confidential Clients SHALL be supported under this profile. Therefore, Public clients SHALL NOT be supported. 238 | 239 | # 7. Tokens 240 | 241 | ## 7.1. ID Token 242 | 243 | > Non-Normative Example - acr 244 | 245 | ``` 246 | { 247 | "iss": "https://www.holder.com.au", 248 | "sub": "a9ebbef6-1f0b-44eb-96cf-0c5b51b37ab2", 249 | "aud": "12345", 250 | "nonce": "n-0S6_WzA2Mj", 251 | "exp": 1311281970, 252 | "iat": 1311280970, 253 | "nbf": 1311280970, 254 | "auth_time": 1311280969, 255 | "acr": "urn:cds.au:cdr:3" 256 | } 257 | ``` 258 | 259 | > Non-Normative Example - vot 260 | 261 | ``` 262 | { 263 | "iss": "https://www.holder.com.au", 264 | "sub": "a9ebbef6-1f0b-44eb-96cf-0c5b51b37ab2", 265 | "aud": "12345", 266 | "nonce": "n-0S6_WzA2Mj", 267 | "exp": 1311281970, 268 | "iat": 1311280970, 269 | "auth_time": 1311280969, 270 | "vot": "CL2", 271 | "vtm": "https://vector.com/trustmark". 272 | } 273 | ``` 274 | 275 | ID Tokens are specified in [section 2](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) of the **[OIDC]** standard. In accordance with **[FAPI-RW]**, ID Tokens must be signed and encrypted when returned 276 | to a Data Recipient from both the Authorisation 277 | Endpoint and Token Endpoint. 278 | 279 | As described under [section 5.2.2](https://openid.net/specs/openid-financial-api-part-2.html#authorization-server) of the **[FAPI-RW]** profile, ID Tokens MUST include the following claims (in addition to the mandatory claims specified in [section 2](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) of the **[OIDC]** standard) as part of [Hybrid Flow authentication](#hybrid): 280 | 281 | - `nonce`: String value used to associate a Client session with an ID Token. 282 | - `s_hash`: Hash of the state value. 283 | - `c_hash`: Hash of the authorisation_code value. 284 | 285 | ID Tokens MUST be signed by Data Holders as specified in [section 8.6](https://openid.net/specs/openid-financial-api-part-2.html#jws-algorithm-considerations) of **[FAPI-RW]**. 286 | 287 | The ID Token returned from the Authorisation Endpoint MUST NOT contain any Personal Information (PI) claims. 288 | 289 | An ID Token MUST not contain both a `vot` claim (see [Vectors of Trust](#vector-loas)) and an `acr` claim . 290 | 291 | If the ID Token contains a `vot` claim, it MUST also contain a `vtm` claim: 292 | 293 | - `vtm`: The trustmark URI as specified in [section 5](https://tools.ietf.org/html/draft-richer-vectors-of-trust-15#section-5) of **[VOT]** . 294 | 295 | ### 7.1.1. Hashing value for state and authorisation code 296 | The `c_hash` value MUST be generated according to [section 3.3.2.11](https://openid.net/specs/openid-connect-core-1_0.html#HybridIDToken) of **[OIDC]**. 297 | 298 | The `s_hash` value MUST be generated according to [section 5.1](https://openid.net/specs/openid-financial-api-part-2.html#introduction) of **[FAPI-RW]**. 299 | 300 | ## 7.2. Access Token 301 | Access Tokens MUST be used as specified in [section 10.3] (https://tools.ietf.org/html/rfc6749#section-10.3) of **[OAUTH2]**. An 302 | Access Token MUST expire `n` minutes after it is issued by the Data Holder where `n` is determined by **[CDR]** rules. 303 | 304 | The process for refreshing an Access Token is described in [section 12.1](https://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken) of **[OIDC]**. 305 | 306 | ## 7.3. Refresh Token 307 | Refresh Tokens MUST be supported by Data Holders. The usage of Refresh Tokens is specified in [section 12](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens) of **[OIDC]**. 308 | A Refresh Token MUST expire `n` days after it is issued where `n` is determined by **[CDR]** rules. 309 | 310 | # 8. Scopes and Claims 311 | Industry-specific scopes (for example, `bank_account`) will not be referenced in 312 | this profile. 313 | 314 | ## 8.1. Scopes 315 | The following scopes MUST be supported: 316 | 317 | - `openid`: As described as [section 3.1.2.1](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) of **[OIDC]**, this scope MUST be present on each authentication request. 318 | - `profile`: Data Holders MUST support the `profile` scope as described in [section 5.4](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) of **[OIDC]**. This scope MAY be present on an authentication request. 319 | 320 | ## 8.2. Claims 321 | The following [normal](https://openid.net/specs/openid-connect-core-1_0.html#NormalClaims) **[OIDC]** claims MUST be supported. This list includes, but is not limited to, **[OIDC]** [standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) : 322 | 323 | - `sub`: [Pairwise Pseudonymous Identifier (PPID)](#identifiers) for the End-User at the Data Holder. 324 | - `acr`: Authentication Context Class Reference. MUST contain a valid [ordinal LoA value](#ordinal-loa). 325 | - `auth_time`: Time when the End-User authentication occurred. Its value is a JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC `auth_time`. 326 | - `name`: End-User's full name in displayable form including all name parts. 327 | - `given_name`: Given name(s) or first name(s) of the End-User. 328 | - `family_name`: Surname(s) or last name(s) of the End-User. 329 | - `updated_at`: Time the End-User's information was last updated. Its value is a JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC `updated_at` time. 330 | 331 | The following **[VOT]** claims MAY be supported: 332 | 333 | - `vot`: MUST contain a valid [VoT value](#vector-loas). 334 | - `vtm`: The **[VOT]** trustmark URI. 335 | 336 | 337 | # 9. Identifiers and Subject Types 338 | The identifier for an authenticated end-user (subject) MUST be passed in the `sub` claim of an [ID Token](https://openid.net/specs/openid-cocnnect-core-1_0.html#IDToken) and [UserInfo response](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse) as defined by **[OIDC]**. The 339 | Data Holder MUST generate the `sub` value as a Pairwise Pseudonymous Identifier (PPID) 340 | as described in [section 8](https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes) of **[OIDC]**. Furthermore, the identifier SHOULD also be unique relative to the scenario in which the end-user has authenticated. For example, the identifier generated for the same person when they are using a business account SHOULD be different to the identifier that is generated when that same individual is authorising as an individual. 341 | 342 | It is RECOMMENDED that the `sub` value is generated as a universally unique 343 | Identifier (UUID) **[RFC4122]**. 344 | 345 | 346 | # 10. Levels of Assurance (LoAs) 347 | Levels Of Assurance (LoAs), returned after a successful authentication, MAY be represented in 2 different forms: 348 | 349 | - [Single Ordinal](#ordinal-loa): A single LoA value is represented. 350 | - Data Holder's MUST support this mechanism. 351 | - [Vector](#vector-loas): One or more LoAs, represented by a vector value, are represented. 352 | - Data Holder's MAY support this mechanism. 353 | 354 | 355 | ## 10.1. Single Ordinal 356 | A Single LoA value is carried in the `acr` claim which is described in [section 2](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) of **[OIDC]**. 357 | 358 | - An LoA of 2 is represented by the URI: `urn:cds.au:cdr:2` 359 | - The authenticator used to attain this level MUST conform with the Credential Level `CL1` rules specified under the [Trusted Digital Identity Framework](https://www.dta.gov.au/our-projects/digital-identity/join-identity-federation/accreditation-and-onboarding/trusted-digital-identity-framework 360 | ) **[TDIF]** Authentication Credential Requirements specification. 361 | 362 | 363 | - An LoA of 3 is represented by the URI: `urn:cds.au:cdr:3` 364 | - The authenticators used to attain this level MUST conform with the Credential Level `CL2` rules specified under the [Trusted Digital Identity Framework](https://www.dta.gov.au/our-projects/digital-identity/join-identity-federation/accreditation-and-onboarding/trusted-digital-identity-framework 365 | ) **[TDIF]** Authentication Credential Requirements specification. 366 | 367 | *READ* operations SHALL only be allowed where __at least__ an LoA of 2 has been achieved. 368 | 369 | *WRITE* operations SHALL only be allowed where __at least__ an LoA of 3 has been achieved. 370 | 371 | 372 | ## 10.2. Vector 373 | 374 | ## 10.2.1. Overview 375 | This profile incorporates support for [Vectors of Trust](https://tools.ietf.org/html/draft-richer-vectors-of-trust-15) **[VOT]**. A Vector, in this context, allows for the representation of multiple orthogonal components dimensions that may, but are not limited to, carry information relating to: 376 | 377 | - Identity Proofing 378 | - Primary Credential Usage 379 | - Primary Credential Management 380 | - Assertion/Federation Presentation 381 | 382 | It is anticipated that due to their characteristics, which include composability, extensibility, and expressiveness, VoTs will be become the relevant standard for assurance representation at Identity Providers. Furthermore, as the **[CDR]** matures and incorporates requirements for Identity Proofing, Credential Management, and Assertion Presentation, these independent LoAs will be progressively added to the VoT **[CDR]** ecosystem. However, the dynamic capabilities of **[VOT]** will ensure that their addition does not break existing **[CDR]** implementations. 383 | 384 | 385 | ## 10.2.2. VoT Values 386 | 387 | The following VoT values SHALL be supported to represent authentication assurance levels when employing **[VOT]**. These are carried in the `vot` claim of an ID Token: 388 | 389 | - `CL1`: This is Credential Level CL1 [defined](https://www.dta.gov.au/our-projects/digital-identity/join-identity-federation/accreditation-and-onboarding/trusted-digital-identity-framework) by the **[TDIF]** Authentication Credential Requirements specification. 390 | 391 | - `CL2`: This is Credential Level CL2 [defined](https://www.dta.gov.au/our-projects/digital-identity/join-identity-federation/accreditation-and-onboarding/trusted-digital-identity-framework) by the **[TDIF]** Authentication Credential Requirements specification. 392 | 393 | *READ* operations SHALL only be allowed where __at least__ a `CL1` has been provided. 394 | 395 | *WRITE* operations SHALL only be allowed where __at least__ a `CL2` has been provided. 396 | 397 | 400 | 401 | # 11. Transaction Security 402 | ## 11.1. Ciphers 403 | All HTTP calls MUST be made using HTTPS incorporating TLS >= 1.2. Only the following cipher suites SHALL be permitted in accordance with [section 8.5](https://openid.net/specs/openid-financial-api-part-2.html#tls-considerations) of **[FAPI-RW]**: 404 | 405 | - TLS\_DHE\_RSA\_WITH\_AES\_128\_GCM\_SHA256 406 | - TLS\_ECDHE\_RSA\_WITH\_AES\_128\_GCM\_SHA256 407 | - TLS\_DHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384 408 | - TLS\_ECDHE\_RSA\_WITH\_AES\_256\_GCM\_SHA384 409 | 410 | 411 | ## 11.2. Mutual TLS 412 | 413 | 416 | 417 | All back-channel communication between Data Recipient and Data Holder systems MUST incorporate, unless stated otherwise, MTLS as part of the TLS handshake: 418 | 419 | - The presented Client transport certificate MUST be issued by the CDR Certificate Authority (CA). The Server MUST NOT trust Client transport certificates issued by other authorities. 420 | - The presented Server transport certificate MUST be issued by the CDR Certificate Authority (CA). The Client MUST NOT trust Server transport certificates issued by other authorities. 421 | 422 | ## 11.3. Holder of Key Mechanism 423 | 424 | MTLS MUST be supported as a Holder of Key (HoK) Mechanism. 425 | 426 | OAUTB SHALL NOT be supported due to a lack industry support. 427 | 428 | MTLS HoK allows issued tokens to be bound to a client certificate as specified in [section 3](https://tools.ietf.org/id/draft-ietf-oauth-mtls-07.html#SenderConstrainedAccess) of **[MTLS]**. 429 | 430 | 431 | # 12. Request Object 432 | 433 | > Non-Normative Example - acr as an Essential Claim 434 | 435 | ``` 436 | #Decoded Request Object JWT 437 | 438 | { 439 | "alg": "PS256", 440 | "typ": "JWT", 441 | "kid": "123" 442 | } 443 | { 444 | "aud": "https://www.recipient.com.au", 445 | "response_type": "code id_token", 446 | "client_id": "12345", 447 | "redirect_uri": "https://www.recipient.com.au/coolstuff", 448 | "scope": "openid", 449 | "state": "af0ifjsldkj", 450 | "nonce": "n-0S6_WzA2Mj", 451 | "claims": { 452 | "id_token": { 453 | "cdr_consent_id": { 454 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 455 | "essential": true 456 | }, 457 | "acr": { 458 | "essential": true, 459 | "values": ["urn:cds.au:cdr:3"] 460 | } 461 | }, 462 | "userinfo": { 463 | "cdr_consent_id": { 464 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 465 | "essential": true 466 | }, 467 | "given_name": null, 468 | "family_name": null 469 | } 470 | } 471 | } 472 | ``` 473 | 474 | The Request Object is a signed and encoded JWT specified in [section 6.1](https://openid.net/specs/openid-connect-core-1_0.html#RequestObject) of **[OIDC]**. As per **[FAPI-RW]** [section 5.2.2](https://openid.net/specs/openid-financial-api-part-2.html#authorization-server) and **[FAPI-CIBA]** [section 5.2.2](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default#markdown-header-522-authorization-server), the `request` parameter MUST be present on requests to both the **[OIDC]** Hybrid Authorisation Endpoint and **[FAPI-CIBA]** Backchannel Authorisation Endpoint. The Request Object enables **[OIDC]** requests to be passed in a single and self-contained parameter. 475 | 476 | Request Objects MUST be signed by Data Recipients as specified in [section 8.6](https://openid.net/specs/openid-financial-api-part-2.html#jws-algorithm-considerations) of **[FAPI-RW]**. 477 | 478 | Data Recipients MUST include a `cdr_consent_id` value in the Request Object. A high-level overview of consent is provided in the [section 14](#consent) of this artifact. 479 | 480 | Data Holder Authorisation Servers MUST treat a Request Object that does not contain a `cdr_consent_id` as an essential claim as invalid. 481 | 482 | Request Object references SHALL NOT be supported. 483 | 484 | The `iss` claim SHALL NOT be supported as it duplicates the role of the `client_id` claim. 485 | 486 | ## 12.1. Data Holder Authorisation Server VoT 487 | 488 | > Non-Normative Example - vtr 489 | 490 | ``` 491 | Decoded Request Object JWT 492 | { 493 | "alg": "PS256", 494 | "typ": "JWT", 495 | "kid": "123" 496 | } 497 | { 498 | "aud": "https://www.recipient.com.au", 499 | "response_type": "code id_token", 500 | "client_id": "12345", 501 | "redirect_uri": "https://www.recipient.com.au/coolstuff", 502 | "scope": "openid", 503 | "state": "af0ifjsldkj", 504 | "nonce": "n-0S6_WzA2Mj", 505 | "vtr":" "CL2 CL1", 506 | "claims": { 507 | "id_token": { 508 | "cdr_consent_id": { 509 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 510 | "essential": true 511 | } 512 | }, 513 | "userinfo": { 514 | "cdr_consent_id": { 515 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 516 | "essential": true 517 | }, 518 | "given_name": null, 519 | "family_name": null 520 | } 521 | } 522 | } 523 | ``` 524 | 525 | If a Data Holder supports Vectors of Trust **[VOT]**, they MUST accept Request objects which MAY contain: 526 | 527 | - A `vtr` value. 528 | - Allowed Values are specified in the [VoT values section](#vot-values) of this artifact. 529 | - This value MUST contain a space-separated string that specifies the `vot` values that the Authorization Server is being requested to use for processing this Authentication Request, with the values appearing in order of preference. The VoT satisfied by the authentication performed is returned as the `vot` Claim Value. 530 | - The `vot` Claim is requested as a Voluntary Claim by this parameter. 531 | - The `vtr` takes precedence over `acr_values` 532 | - A `vot` essential claim. 533 | - This is the VoT equivalent of an `acr` essential claim. 534 | - If the `vot` Claim is requested as an Essential Claim for the ID Token with a values parameter requesting specific VoT values, the Data Holder Authorization Server MUST return a `vot` Claim Value that matches one of the requested values. The Data Holder Authorization Server MAY ask the End-User to re-authenticate with additional factors to meet this requirement. If this requirement cannot be met, then the Data Holder Authorization Server MUST treat that outcome as a failed authentication. 535 | 536 | ## 12.2. Data Recipient Client using VoT 537 | 538 | > Non-Normative Example - vot as an Essential Claim 539 | 540 | ``` 541 | Decoded Request Object JWT 542 | { 543 | "alg": "PS256", 544 | "typ": "JWT", 545 | "kid": "123" 546 | } 547 | { 548 | "aud": "https://www.recipient.com.au", 549 | "response_type": "code id_token", 550 | "client_id": "12345", 551 | "redirect_uri": "https://www.recipient.com.au/coolstuff", 552 | "scope": "openid", 553 | "state": "af0ifjsldkj", 554 | "nonce": "n-0S6_WzA2Mj", 555 | "claims": { 556 | "id_token": { 557 | "vot": { 558 | "essential": true, 559 | "values": ["CL2"] 560 | }, 561 | "cdr_consent_id": { 562 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 563 | "essential": true 564 | } 565 | } 566 | } 567 | } 568 | ``` 569 | 570 | For *WRITE* operations, a Data Recipient: 571 | 572 | - SHALL, where a Data Holder supports **[VOT]**, request user authentication with a Credential Level of 2 (`CL2`) or greater by requesting the `vot` claim as an essential claim. 573 | 574 | # 13. Endpoints 575 | 576 | ## 13.1. OpenID Provider Configuration Endpoint 577 | 578 | > Non-Normative Example 579 | 580 | ``` 581 | # Request 582 | 583 | GET /.well-known/openid-configuration HTTP/1.1 584 | Host: www.dh.com.au 585 | 586 | # Response 587 | 588 | HTTP/1.1 200 OK 589 | Content-Type: application/json 590 | { 591 | "issuer": "https://www.dh.com.au", 592 | "authorization_endpoint": "https://www.dh.com.au/authorise", 593 | "token_endpoint": "https://www.dh.com.au/token", 594 | "introspection_endpoint": "https://www.dh.com.au/introspect", 595 | "revocation_endpoint": "https://www.dh.com.au/revoke", 596 | "userinfo_endpoint": "https://www.dh.com.au/userinfo", 597 | "jwks_uri": "https://www.dh.com.au/jwks", 598 | "registration_endpoint": "https://www.dh.com.au/register", 599 | "backchannel_authentication_endpoint": "https://www.dh.com.au/bc-authorise", 600 | "backchannel_token_delivery_modes_supported": ["poll", "ping"], 601 | "backchannel_authentication_request_signing_alg_values_supported": ["ES256", "PS256"], 602 | "scopes_supported": ["openid", "profile"], 603 | "response_types_supported": ["code id_token"], 604 | "response_modes_supported": ["fragment"], 605 | "grant_types_supported": ["authorization_code", "client_credentials", "urn:openid:params:modrna:grant-type:backchannel_request"], 606 | "acr_values_supported": ["urn:cds.au:cdr:2","urn:cds.au:cdr:3"], 607 | "vot_values_supported": ["CL1","CL2"], 608 | "subject_types_supported": ["pairwise"], 609 | "id_token_signing_alg_values_supported": ["ES256", "PS256"], 610 | "request_object_signing_alg_values_supported": ["ES256", "PS256"], 611 | "token_endpoint_auth_methods_supported": ["private_key_jwt"], 612 | "mutual_tls_sender_constrained_access_tokens": "true", 613 | "claims_supported": ["name", "given_name", "family_name", "vot", "acr", "auth_time", "sub"] 614 | } 615 | ``` 616 | 617 | 620 | 621 | | Description | Value | 622 | |---|---| 623 | | Hosted By | Data Holder | 624 | | Transport Security | TLS | 625 | | Client Authentication Required| No| 626 | | Bearer Token Required| No| 627 | 628 | Data Holders MUST make their OpenID Provider Metadata available via a configuration endpoint as outlined in [Section 3 and 4 of the OpenID Connect Discovery standards] (https://openid.net/specs/openid-connect-discovery-1_0.html) **[OIDD]**. 629 | 630 | Where a Data Holder is supporting [Vectors of Trust](https://tools.ietf.org/html/draft-richer-vectors-of-trust-15) **[VOT]** or [FAPI-CIBA](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default) **[FAPI-CIBA]**, the published OpenID Provider metadata SHALL reflect that support. 631 | 632 | At a minimum, the Data Provider metadata MUST include: 633 | 634 | - `issuer`: URL that the Data Holder asserts as its Issuer Identifier. 635 | - `authorization_endpoint`: URL of the Authorization Endpoint. 636 | - `token_endpoint`: URL of the Token Endpoint. 637 | - `introspection_endpoint`: URL of the Introspection Endpoint. 638 | - `revocation_endpoint`: URL of the Revocation Endpoint. 639 | - `userinfo_endpoint`: URL of the UserInfo Endpoint. 640 | - `jwks_uri`: URL of the JWKS Endpoint. 641 | - `scopes_supported`: This list of supported scopes. 642 | - `claims_supported`: The list of supported claims. 643 | - `acr_values_supported`: The supported ACR values. 644 | 645 | Data Holders that support [Vectors of Trust](https://tools.ietf.org/html/draft-richer-vectors-of-trust-15) **[VOT]** MUST include: 646 | 647 | - `vot_values_supported`: The list of supported component values. 648 | 649 | Data Holders that support [CIBA](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default) **[FAPI-CIBA]** MUST include: 650 | 651 | - `backchannel_authentication_endpoint`: The CIBA Authorisation Endpoint. 652 | - `backchannel_authentication_request_signing_alg_values_supported`: JSON array containing a list of the JWS signing algorithms (alg values) supported by the OP for signed authentication requests. Only `ES256` and `PS256` SHALL be supported. 653 | 654 | 655 | ## 13.2. Authorisation Endpoint 656 | 657 | > Non-Normative Example 658 | 659 | ``` 660 | # Request 661 | 662 | GET /authorise? 663 | response_type=code%20id_token 664 | &client_id=12345 665 | &redirect_uri=https%3A%2F%2Fwww.recipient.com.au%2Fcoolstuff 666 | &scope=openid%20profile 667 | &nonce=n-0S6_WzA2Mj 668 | &state=af0ifjsldkj HTTP/1.1 669 | &request=eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.ey ... 670 | Host: www.holder.com.au 671 | 672 | # Decoded request JWT 673 | { 674 | "alg": "PS256", 675 | "typ": "JWT", 676 | "kid": "123" 677 | } 678 | { 679 | "iss": "12345", 680 | "aud": "https://www.recipient.com.au", 681 | "response_type": "code id_token", 682 | "client_id": "12345", 683 | "redirect_uri": "https://www.recipient.com.au/coolstuff", 684 | "scope": "openid", 685 | "state": "af0ifjsldkj", 686 | "nonce": "n-0S6_WzA2Mj", 687 | "claims": { 688 | "userinfo": { 689 | "cdr_consent_id": { 690 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 691 | "essential": true 692 | }, 693 | "given_name": null, 694 | "family_name": null 695 | }, 696 | "id_token": { 697 | "cdr_consent_id": { 698 | "value": "adceecd3-3437-4369-909e-1ac82abdc288", 699 | "essential": true 700 | }, 701 | "acr": { 702 | "values": ["urn:cds.au:cdr:3"] 703 | } 704 | } 705 | } 706 | } 707 | 708 | ``` 709 | 710 | | Description | Value | 711 | |---|---| 712 | | Hosted By | Data Holder | 713 | | Transport Security | TLS | 714 | | Client Authentication Required| No| 715 | | Bearer Token Required| No| 716 | 717 | The requirements for the Authorisation Endpoint are specified in [section 3.3.2] (https://openid.net/specs/openid-connect-core-1_0.html#HybridAuthorizationEndpoint) of **[OIDC]** and further specified under section [5.2.2](https://openid.net/specs/openid-financial-api-part-2.html#authorization-server) of **[FAPI-RW]**. This endpoint is invoked as part of the [Hybrid Authentication flow](#hybrid-flow). 718 | 719 | Only a `response_type` (see [section 3](https://openid.net/specs/openid-connect-core-1_0.html#Authentication) of **[OIDC]**) of `code id_token` SHALL be allowed. 720 | 721 | The `request_uri` parameter SHALL NOT be supported. 722 | 723 | A description of requirements relating to the `request` parameter can be found in the [section 12](#request-object). 724 | 725 | ## 13.3. Backchannel Authorisation Endpoint 726 | | Description | Value | 727 | |---|---| 728 | | Hosted By | Data Holder | 729 | | Transport Security | MTLS | 730 | | Client Authentication Required| Yes| 731 | | Bearer Token Required| No| 732 | 733 | The requirements for the Backchannel Authorisation Endpoint are specified in the [Client Initiated Backchannel Authentication Profile](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default#markdown-header-523-confidential-client) **[FAPI-CIBA]**. This endpoint is invoked as part of the [Client-Initiated Backchannel Authentication flow](#ciba-flow). 734 | 735 | Data Holder's that feature **[FAPI-CIBA]** MUST support the `poll` mode and MAY support the `ping` mode. The `push` mode SHALL not be supported. 736 | 737 | A description of requirements relating to the `request` parameter can be found in the [section 12](#request-object). 738 | 739 | ## 13.4. Token Endpoint 740 | | Description | Value | 741 | |---|---| 742 | | Hosted By | Data Holder | 743 | | Transport Security | MTLS | 744 | | Client Authentication Required| Yes| 745 | | Bearer Token Required| No| 746 | 747 | The requirements for the Token Endpoint are specified in [section 5.3] (https://openid.net/specs/openid-connect-core-1_0.html#UserInfo) of **[OIDC]**. 748 | 749 | To obtain an Access Token, an ID Token, and a Refresh Token, the Data Recipient sends a Token Request to the Token Endpoint. 750 | 751 | Data Holders MUST support a Token Endpoint. 752 | 753 | ## 13.5. UserInfo Endpoint 754 | | Description | Value | 755 | |---|---| 756 | | Hosted By | Data Holder | 757 | | Transport Security | MTLS | 758 | | Client Authentication Required| No| 759 | | Bearer Token Required| Yes| 760 | 761 | The requirements for the UserInfo Endpoint are specified in [section 3.3.3] (https://openid.net/specs/openid-connect-core-1_0.html#HybridTokenEndpoint) of **[OIDC]**. 762 | 763 | Data Holders MUST support a UserInfo Endpoint. 764 | 765 | ## 13.6. JWKS Endpoint 766 | 767 | > Non-Normative Example 768 | 769 | ``` 770 | { 771 | "keys": [ 772 | { 773 | "kty":"EC", 774 | "crv":"P-256", 775 | "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", 776 | "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", 777 | "use":"enc", 778 | "kid":"1" 779 | } 780 | ] 781 | } 782 | ``` 783 | 784 | 787 | 788 | 791 | 792 | | Description | Value | 793 | |---|---| 794 | | Hosted By | Registry | 795 | | Transport Security | TLS | 796 | | Client Authentication Required| No| 797 | | Bearer Token Required| No| 798 | 799 | The JWKS Endpoint returns a **[JSON]** document containing a JSON Web Key Set described in [section 5](https://tools.ietf.org/html/rfc7517#section-5) of **[JWK]**. The JWK format is described in [section 4](https://tools.ietf.org/html/rfc7517#section-4) of **[JWK]**. In addition to the mandatory fields specified in **[JWK]**, each JWK MUST include, at a minimum, the following fields: 800 | 801 | - `kid`: This is used to match a specific key within a JWKS and thus must be unique within the set. 802 | - `use`: This is used to identify the intended use of the public key. Supported values are `sig` and `enc`. 803 | 804 | ## 13.7. Introspection Endpoint 805 | 806 | | Description | Value | 807 | |---|---| 808 | | Hosted By | Data Holder | 809 | | Transport Security | MTLS | 810 | | Client Authentication Required| Yes| 811 | | Bearer Token Required| No| 812 | 813 | Data Holders MUST implement an Introspection Endpoint to allow Data Recipients to determine the status and expiry date of Refresh Tokens. The requirements for an Introspection Endpoint are described in [section 2](https://tools.ietf.org/html/rfc7662#section-2) of **[RFC7662]**. 814 | 815 | Introspection of Refresh Tokens MUST be supported. 816 | 817 | Introspection of Access Tokens and ID Tokens MUST NOT be supported. 818 | 819 | An Introspection Endpoint Response SHALL only include the following fields: 820 | 821 | - `active`: Boolean indicator of whether or not the presented token 822 | is currently active. 823 | - `exp`: A JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC expiry time. 824 | 825 | ## 13.8. Revocation Endpoint 826 | 827 | | Description | Value | 828 | |---|---| 829 | | Hosted By | Data Holder | 830 | | Transport Security | MTLS | 831 | | Client Authentication Required| Yes| 832 | | Bearer Token Required| No| 833 | 834 | Data Holders MUST implement a Token Revocation Endpoint as described in [section 2](https://tools.ietf.org/html/rfc7009#section-2) of **[RFC7009]**. The Revocation Endpoint serves as a revocation mechanism that allows a Data Recipient to invalidate its tokens as required. Notifying the Data Holder authorisation server that the token is no longer needed allows the server to clean up data associated with that token and the underlying authorization grant. 835 | 836 | Revocation of Refresh Tokens and Access Tokens MUST be supported. 837 | 838 | ## 13.9. Client Registration Endpoint 839 | 840 | > Non-Normative Example 841 | 842 | ``` 843 | # Request 844 | 845 | POST /clients HTTP/1.1 846 | Content-Type: application/jwt 847 | Accept: application/json 848 | Host: www.holder.com.au 849 | 850 | eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMzQ1In0.ey ... 851 | 852 | # Decoded request JWT 853 | { 854 | "alg": "PS256", 855 | "typ": "JWT", 856 | "kid": "12345" 857 | } 858 | { 859 | "iss": "https://www.recipient.com.au", 860 | "iat": 1516239022, 861 | "exp": 1516239322, 862 | "aud": "https://www.holder.com.au", 863 | "jti": "37747cd1-c105-4569-9f75-4adf28b73e31", 864 | "redirect_uris": ["https://www.recipient.com.au/coolstuff"], 865 | "token_endpoint_auth_method": "private_key_jwt", 866 | "grant_types": ["authorization_code","client_credentials"], 867 | "response_types": "code", 868 | "software_statement": "encodedsignedjwt", 869 | "id_token_signed_response_alg":"PS256", 870 | "request_object_signing_alg":"PS256" 871 | } 872 | 873 | # Response 874 | 875 | HTTP/1.1 201 OK 876 | Content-Type: application/json 877 | { 878 | "client_id": "12345", 879 | "client_name": "Awesome Recipient Software", 880 | "redirect_uris": ["https://www.recipient.com.au/coolstuff"], 881 | "token_endpoint_auth_method": "private_key_jwt", 882 | "grant_types": ["authorization_code","client_credentials"], 883 | "response_types": "code", 884 | "id_token_signed_response_alg":"PS256", 885 | "request_object_signing_alg":"PS256" 886 | } 887 | ``` 888 | 889 | 892 | 893 | | Description | Value | 894 | |---|---| 895 | | Hosted By | Data Holder | 896 | | Transport Security | MTLS | 897 | | Client Authentication Required| No| 898 | | Bearer Token Required| No| 899 | 900 | ### 13.9.1. Request 901 | 902 | To register as a new Client at a Data Holder's Authorisation Server, a Data Recipient MUST `POST` its Client metadata to the Data Holder's Registration Endpoint in the form of an (encoded) signed [JWT](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32) **[JWT]**. This process is specified in [OpenID Connect Registration](https://openid.net/specs/openid-connect-registration-1_0.html) **[OIDC-CR]**. The registering **[JWT]** is signed by the private key of the Client and MUST include a [software statement](https://tools.ietf.org/html/rfc7591#page-14). The software statement is an encoded [JWT](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32) **[JWT]** signed by the CDR Certificate Authority private key and thus supports non-repudiation. The content of and mechanism for retrieving and generating a software statement is beyond the scope of this profile. 903 | 904 | The registering **[JWT]** MUST include, at a minimum, the following fields: 905 | 906 | - `iss`: The Data Recipient identifier specified at the Registry. 907 | - `iat`: A JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC issued at time. 908 | - `exp`: A JSON number representing the number of seconds from 1970-01-01T00:00:00Z to the UTC expiry time. 909 | - `aud`: The Data Holder identifier specified at the Registry. 910 | - `jti`: A unique identifier generated by the Data Recipient. 911 | - `redirect_uris`: An Array of Redirection URI values. 912 | - `software_statement`: This is an encoded JWT which includes several claims that describe the Data Recipient application and the Data Recipient organisation. 913 | - `id_token_signed_response_alg`: Token Endpoint preferred signing algorithm. 914 | - `request_object_signing_alg`: Request Object signing algorithm. 915 | - `token_endpoint_auth_method`: The chosen Client authentication mechanism. 916 | 917 | If the Data Holder supports [FAPI-CIBA](https://bitbucket.org/openid/fapi/src/master/Financial_API_WD_CIBA.md?fileviewer=file-view-default) **[FAPI-CIBA]** and the Client wishes to utilise this feature, the registration MUST include the following fields: 918 | 919 | - `backchannel_token_delivery_mode`: This MUST be set to a value of `ping` or `poll`. `push` mode SHALL NOT be supported. 920 | - `backchannel_authentication_request_signing_alg`: MUST be set to `ES256` or `PS256`. 921 | 922 | If the Client supports a delivery mode of `ping`, the registration MUST include the following fields: 923 | 924 | - `backchannel_client_notification_endpoint`: This is the endpoint to which the OP will post a notification after a successful or failed end-user authentication. 925 | 926 | This request MUST be made with MTLS as specified in [section 11.2](#mutual-tls). 927 | 928 | Data Holders MUST ensure that the `CN` (Common Name) in the Client certificate `subject` field matches the `software_id` claim present in the software statement. 929 | Data Holders MUST verify that the embedded software statement has been signed by the CDR Certificate Authority. 930 | 931 | ### 13.9.2. Response 932 | 933 | The Data Holder MUST respond in accordance with [OpenID Connect Registration](https://openid.net/specs/openid-connect-registration-1_0.html) **[OIDC-CR]** sections 3.2 and 3.3. 934 | 935 | 936 | # 14. Consent 937 | 938 | 941 | 942 | Prior to initiating an authentication request to a Data Holder's Authorisation Server, a Data Recipient MUST have captured indicative Consumer Consent and passed this to the Data Holder. A Consent occurrence is assigned a unique `cdr_consent_id` and is referenced by the Data Holder as part of an authorisation process with a Consumer. This process binds the Consent to the authorisation. In order to support this functionality, a Data Holder MUST implement and host an API to support the creation of a Consent, the querying of a Consent, and the deletion of a Consent. In this instance the Data Recipient is to be considered the Resource Owner of the Consent occurrence. 943 | 944 | The specifics of the Consent API and processing of Consent are beyond the scope of this document. 945 | 946 | A Data Holder Token Endpoint MUST: 947 | 948 | - Support the `grant type` of `client_credentials` strictly for the purpose of passing an Access Token to a Data Recipient which can be then used to invoke the Consent API. 949 | 950 | 951 | # 15. Normative References 952 | 953 | | **Reference** | **Description** | 954 | | --- | --- | --- | 955 | | **[CIBA]** | OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 draft-01: | 956 | | **[FAPI-CIBA]** | Financial Services – Financial API: Client Initiated Backchannel Authentication Profile 1.0: | 957 | | **[FAPI-R]** | Financial-grade API - Part 1: Read Only API Security Profile: | 958 | | **[FAPI-RW]** | Financial-grade API - Part 2: Read and Write API Security Profile: | 959 | | **[JSON]** | The JavaScript Object Notation (JSON) Data Interchange Format: | 960 | | **[JWA]** | JSON Web Algorithms (JWA): | 961 | | **[JWK]** | JSON Web Key (JWK): | 962 | | **[JWT]** | JSON Web Token (JWT): | 963 | | **[JWS]** | JSON Web Signature (JWS): | 964 | | **[JWE]** | JSON Web Encryption (JWE): | 965 | | **[MTLS]** | OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens: | 966 | | **[OAUTH2]** | The OAuth 2.0 Authorization Framework: | 967 | | **[OIDC]** | OpenID Connect Core 1.0 incorporating errata set 1: | 968 | | **[OIDD]** | OpenID Connect Discovery 1.0 incorporating errata set 1: | 969 | | **[OIDC-CR]** | OpenID Connect Dynamic Client Registration 1.0 incorporating errata set 1: | 970 | | **[TDIF]** | Digital Transformation Agency - Trusted Digital Identity Framework 971 | | **[RFC2119]** | Key words for use in RFCs to Indicate Requirement Levels | 972 | | **[RFC7009]** | OAuth 2.0 Token Revocation: | 973 | | **[RFC7523]** | JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants: | 974 | | **[RFC7662]** | OAuth 2.0 Token Introspection: | 975 | | **[VOT]** | Vectors of Trust, draft-richer-vectors-of-trust-15 976 | 977 | # 16. Informative References 978 | 979 | | **Reference** | **Description** | 980 | |----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 981 | | **[BCP195]** | Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS): 982 | | **[CDR]** | Consumer Data Right: | 983 | | **[FAPI]** | Financial-Grade API - Home Page | 984 | | **[RFC4122]** | A Universally Unique Identifier (UUID) URN Namespace: | 985 | | **[X.1254]** | X.1254 - Entity authentication assurance framework: | 986 | 987 | # 17. Appendix 988 | 989 | ## 17.1. Client Credentials grant type 990 | ![Part A](/images/clientCredentialsSequence.png) 991 | 992 | ## 17.2. Redirect Authentication Flow 993 | 994 | ### Part A - Data Recipient to Data Holder 995 | ![Part A](/images/redirPartA.png) 996 | #### Steps 997 | 1. The end-user navigates to a Data Recipient Website. 998 | 2. The end-user selects their preferred Data Holder. 999 | 3. The end-user's browser is redirected to the Data Holder's Authorisation Endpoint. 1000 | 4. *One* of the following may occur: 1001 | 1. The end-user may cancel the process at any point (in Parts **A**, **B** or **C**) and will be returned to the passed redirection URI for the Data Recipient with the relevant error code. 1002 | 2. The end-user is denied access. This may happen as a result of too many failed attempts or other conditions relating to the end-user's account. The end-user's browser will be redirected to the passed redirection URI for the Data Recipient with the relevant error code. 1003 | 3. The end-user successfully authenticates and begins the authorisation step (see Part **B**). 1004 | 1005 | 1006 | ### Part B - Data Holder Authentication 1007 | ![Part B](/images/redirPartB.png) 1008 | #### Steps 1009 | Part **B** illustrates the different authentication methods a Data Holder may present to the end-user. It is important from a usability perspective that the Data Holder authentication choices presented to the end-user are consistent with those currently utilised by the end-user when accessing their existing Data Holder online accounts. 1010 | 1011 | The following options may be used: 1012 | 1013 | 1. All Credentials/Factors are captured through the Browser. On success, the authorisation process begins (Part **C**) . 1014 | 2. Two Factor Authentication (2FA) 1015 | 1. A userId and optionally a password are entered to the browser and submitted by the end-user. 1016 | 2. A code or notification is sent to a end-user's pre-registered mobile/device application (detached authentication device). This step is optional as an end-user's device application may generate codes in isolation, as is the case for Time-based One-Time Password (TOTP). 1017 | 3. The end-user views the code or event on their detached authentication device. 1018 | 4. *One* of the following may occur: 1019 | 1. The end-user directly enters the code (or scans a QR Code) into the browser and submits the request. On success, the authorisation process begins (Part **C**). 1020 | 2. The end-user does not enter the code into the browser. The end-user acknowledges the authentication through the device and a secure message is sent from the device to the Data Holder via a backchannel. On receipt of the message, the Data Holder's website redirects the end-user's browser to the authorisation page (Part **C**). 1021 | 1022 | ### Part C - Post Authorisation Data Recipient to Data Holder 1023 | ![Part C](/images/redirPartC.png) 1024 | #### Steps 1025 | This process continues from Part **B** after a successful authentication. 1026 | 1027 | 1. The end-user authorises the transaction. 1028 | 2. *One* of the following may occur: 1029 | 1. The Data Holder creates a new pairwise identifier for the end-user and Data Recipient combination. This is the first time the end-user has authenticated to the Data Holder in the context of a request from this Data Recipient. 1030 | 2. This is a reauthentication. The end-user has previously authenticated to the Data Holder in the context of an authentication request from this Data Recipient. The existing pairwise identifier for the end-user and Data Recipient is allocated to the authorisation. 1031 | 3. The Data Holder creates the authorisation code and ID Token for the authorisation instance. 1032 | 4. The end-user's browser is redirected to the Data Recipient's redirect URI. The ID Token and authorisation code generated in Step 3 are attached to the URL as a fragment. The Data Recipient web server processes the request. 1033 | 5. The Data Recipient decrypts the ID Token, verifies the signature and issuer of the ID Token, verifies the state/code hashes within the token, and also matches the presented state against its own session state. The Data Recipient then sends a POST request to the Data Holder Token Endpoint using Client Authentication and the Authorisation Code. 1034 | 6. The Data Holder Endpoint authenticates the Data Recipient client and matches the authorisation code. On success, the Endpoint responds with an Access Token, Refresh Token and an ID Token. 1035 | 7. The Data Holder creates an event relating to the authorisation. This event is propagated/handled and may result in shared resource owners being notified about the authorisation. 1036 | 8. The Data Recipient verifies the ID Token and on success, invokes the UserInfo Endpoint using the Access Token as a Bearer Token. The Data Holder verifies the token, applies the necessary Holder of Key verification check and on success, returns the requested UserInfo claims. 1037 | 9. The Data Recipient optionally begins calling the Data Holder APIs with the Access Token and renders the result to the end-user's browser. 1038 | 1039 | ## 17.3. Sample Data Holder Domain Model 1040 | ![Domain Model](/images/holderDomain.png) 1041 | ### Description 1042 | This diagram depicts the domain model of a hypothetical Data Holder. It is in no way prescriptive but illustrates the associations between the authorisation-related entities that may exist within a Data Holder's domain. 1043 | -------------------------------------------------------------------------------- /slate/source/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require ./all_nosearch 2 | //= require ./app/_search 3 | -------------------------------------------------------------------------------- /slate/source/javascripts/all_nosearch.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_toc 3 | //= require ./app/_lang 4 | 5 | $(function() { 6 | loadToc($('#toc'), '.toc-link', '.toc-list-h2', 10); 7 | setupLanguages($('body').data('languages')); 8 | $('.content').imagesLoaded( function() { 9 | window.recacheHeights(); 10 | window.refreshToc(); 11 | }); 12 | }); 13 | 14 | window.onpopstate = function() { 15 | activateLanguage(getLanguageFromQueryString()); 16 | }; 17 | -------------------------------------------------------------------------------- /slate/source/javascripts/app/_lang.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | 3 | /* 4 | Copyright 2008-2013 Concur Technologies, Inc. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); you may 7 | not use this file except in compliance with the License. You may obtain 8 | a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | License for the specific language governing permissions and limitations 16 | under the License. 17 | */ 18 | ;(function () { 19 | 'use strict'; 20 | 21 | var languages = []; 22 | 23 | window.setupLanguages = setupLanguages; 24 | window.activateLanguage = activateLanguage; 25 | window.getLanguageFromQueryString = getLanguageFromQueryString; 26 | 27 | function activateLanguage(language) { 28 | if (!language) return; 29 | if (language === "") return; 30 | 31 | $(".lang-selector a").removeClass('active'); 32 | $(".lang-selector a[data-language-name='" + language + "']").addClass('active'); 33 | for (var i=0; i < languages.length; i++) { 34 | $(".highlight.tab-" + languages[i]).hide(); 35 | $(".lang-specific." + languages[i]).hide(); 36 | } 37 | $(".highlight.tab-" + language).show(); 38 | $(".lang-specific." + language).show(); 39 | 40 | window.recacheHeights(); 41 | 42 | // scroll to the new location of the position 43 | if ($(window.location.hash).get(0)) { 44 | $(window.location.hash).get(0).scrollIntoView(true); 45 | } 46 | } 47 | 48 | // parseURL and stringifyURL are from https://github.com/sindresorhus/query-string 49 | // MIT licensed 50 | // https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license 51 | function parseURL(str) { 52 | if (typeof str !== 'string') { 53 | return {}; 54 | } 55 | 56 | str = str.trim().replace(/^(\?|#|&)/, ''); 57 | 58 | if (!str) { 59 | return {}; 60 | } 61 | 62 | return str.split('&').reduce(function (ret, param) { 63 | var parts = param.replace(/\+/g, ' ').split('='); 64 | var key = parts[0]; 65 | var val = parts[1]; 66 | 67 | key = decodeURIComponent(key); 68 | // missing `=` should be `null`: 69 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 70 | val = val === undefined ? null : decodeURIComponent(val); 71 | 72 | if (!ret.hasOwnProperty(key)) { 73 | ret[key] = val; 74 | } else if (Array.isArray(ret[key])) { 75 | ret[key].push(val); 76 | } else { 77 | ret[key] = [ret[key], val]; 78 | } 79 | 80 | return ret; 81 | }, {}); 82 | }; 83 | 84 | function stringifyURL(obj) { 85 | return obj ? Object.keys(obj).sort().map(function (key) { 86 | var val = obj[key]; 87 | 88 | if (Array.isArray(val)) { 89 | return val.sort().map(function (val2) { 90 | return encodeURIComponent(key) + '=' + encodeURIComponent(val2); 91 | }).join('&'); 92 | } 93 | 94 | return encodeURIComponent(key) + '=' + encodeURIComponent(val); 95 | }).join('&') : ''; 96 | }; 97 | 98 | // gets the language set in the query string 99 | function getLanguageFromQueryString() { 100 | if (location.search.length >= 1) { 101 | var language = parseURL(location.search).language; 102 | if (language) { 103 | return language; 104 | } else if (jQuery.inArray(location.search.substr(1), languages) != -1) { 105 | return location.search.substr(1); 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | 112 | // returns a new query string with the new language in it 113 | function generateNewQueryString(language) { 114 | var url = parseURL(location.search); 115 | if (url.language) { 116 | url.language = language; 117 | return stringifyURL(url); 118 | } 119 | return language; 120 | } 121 | 122 | // if a button is clicked, add the state to the history 123 | function pushURL(language) { 124 | if (!history) { return; } 125 | var hash = window.location.hash; 126 | if (hash) { 127 | hash = hash.replace(/^#+/, ''); 128 | } 129 | history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash); 130 | 131 | // save language as next default 132 | localStorage.setItem("language", language); 133 | } 134 | 135 | function setupLanguages(l) { 136 | var defaultLanguage = localStorage.getItem("language"); 137 | 138 | languages = l; 139 | 140 | var presetLanguage = getLanguageFromQueryString(); 141 | if (presetLanguage) { 142 | // the language is in the URL, so use that language! 143 | activateLanguage(presetLanguage); 144 | 145 | localStorage.setItem("language", presetLanguage); 146 | } else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) { 147 | // the language was the last selected one saved in localstorage, so use that language! 148 | activateLanguage(defaultLanguage); 149 | } else { 150 | // no language selected, so use the default 151 | activateLanguage(languages[0]); 152 | } 153 | } 154 | 155 | // if we click on a language tab, activate that language 156 | $(function() { 157 | $(".lang-selector a").on("click", function() { 158 | var language = $(this).data("language-name"); 159 | pushURL(language); 160 | activateLanguage(language); 161 | return false; 162 | }); 163 | }); 164 | })(); 165 | -------------------------------------------------------------------------------- /slate/source/javascripts/app/_search.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_lunr 2 | //= require ../lib/_jquery 3 | //= require ../lib/_jquery.highlight 4 | ;(function () { 5 | 'use strict'; 6 | 7 | var content, searchResults; 8 | var highlightOpts = { element: 'span', className: 'search-highlight' }; 9 | var searchDelay = 0; 10 | var timeoutHandle = 0; 11 | 12 | var index = new lunr.Index(); 13 | 14 | index.ref('id'); 15 | index.field('title', { boost: 10 }); 16 | index.field('body'); 17 | index.pipeline.add(lunr.trimmer, lunr.stopWordFilter); 18 | 19 | $(populate); 20 | $(bind); 21 | 22 | function populate() { 23 | $('h1, h2').each(function() { 24 | var title = $(this); 25 | var body = title.nextUntil('h1, h2'); 26 | index.add({ 27 | id: title.prop('id'), 28 | title: title.text(), 29 | body: body.text() 30 | }); 31 | }); 32 | 33 | determineSearchDelay(); 34 | } 35 | function determineSearchDelay() { 36 | if(index.tokenStore.length>5000) { 37 | searchDelay = 300; 38 | } 39 | } 40 | 41 | function bind() { 42 | content = $('.content'); 43 | searchResults = $('.search-results'); 44 | 45 | $('#input-search').on('keyup',function(e) { 46 | var wait = function() { 47 | return function(executingFunction, waitTime){ 48 | clearTimeout(timeoutHandle); 49 | timeoutHandle = setTimeout(executingFunction, waitTime); 50 | }; 51 | }(); 52 | wait(function(){ 53 | search(e); 54 | }, searchDelay ); 55 | }); 56 | } 57 | 58 | function search(event) { 59 | 60 | var searchInput = $('#input-search')[0]; 61 | 62 | unhighlight(); 63 | searchResults.addClass('visible'); 64 | 65 | // ESC clears the field 66 | if (event.keyCode === 27) searchInput.value = ''; 67 | 68 | if (searchInput.value) { 69 | var results = index.search(searchInput.value).filter(function(r) { 70 | return r.score > 0.0001; 71 | }); 72 | 73 | if (results.length) { 74 | searchResults.empty(); 75 | $.each(results, function (index, result) { 76 | var elem = document.getElementById(result.ref); 77 | searchResults.append("
  • " + $(elem).text() + "
  • "); 78 | }); 79 | highlight.call(searchInput); 80 | } else { 81 | searchResults.html('
  • '); 82 | $('.search-results li').text('No Results Found for "' + searchInput.value + '"'); 83 | } 84 | } else { 85 | unhighlight(); 86 | searchResults.removeClass('visible'); 87 | } 88 | } 89 | 90 | function highlight() { 91 | if (this.value) content.highlight(this.value, highlightOpts); 92 | } 93 | 94 | function unhighlight() { 95 | content.unhighlight(highlightOpts); 96 | } 97 | })(); 98 | 99 | -------------------------------------------------------------------------------- /slate/source/javascripts/app/_toc.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | //= require ../lib/_imagesloaded.min 3 | ;(function () { 4 | 'use strict'; 5 | 6 | var htmlPattern = /<[^>]*>/g; 7 | var loaded = false; 8 | 9 | var debounce = function(func, waitTime) { 10 | var timeout = false; 11 | return function() { 12 | if (timeout === false) { 13 | setTimeout(function() { 14 | func(); 15 | timeout = false; 16 | }, waitTime); 17 | timeout = true; 18 | } 19 | }; 20 | }; 21 | 22 | var closeToc = function() { 23 | $(".toc-wrapper").removeClass('open'); 24 | $("#nav-button").removeClass('open'); 25 | }; 26 | 27 | function loadToc($toc, tocLinkSelector, tocListSelector, scrollOffset) { 28 | var headerHeights = {}; 29 | var pageHeight = 0; 30 | var windowHeight = 0; 31 | var originalTitle = document.title; 32 | 33 | var recacheHeights = function() { 34 | headerHeights = {}; 35 | pageHeight = $(document).height(); 36 | windowHeight = $(window).height(); 37 | 38 | $toc.find(tocLinkSelector).each(function() { 39 | var targetId = $(this).attr('href'); 40 | if (targetId[0] === "#") { 41 | headerHeights[targetId] = $(targetId).offset().top; 42 | } 43 | }); 44 | }; 45 | 46 | var refreshToc = function() { 47 | var currentTop = $(document).scrollTop() + scrollOffset; 48 | 49 | if (currentTop + windowHeight >= pageHeight) { 50 | // at bottom of page, so just select last header by making currentTop very large 51 | // this fixes the problem where the last header won't ever show as active if its content 52 | // is shorter than the window height 53 | currentTop = pageHeight + 1000; 54 | } 55 | 56 | var best = null; 57 | for (var name in headerHeights) { 58 | if ((headerHeights[name] < currentTop && headerHeights[name] > headerHeights[best]) || best === null) { 59 | best = name; 60 | } 61 | } 62 | 63 | // Catch the initial load case 64 | if (currentTop == scrollOffset && !loaded) { 65 | best = window.location.hash; 66 | loaded = true; 67 | } 68 | 69 | var $best = $toc.find("[href='" + best + "']").first(); 70 | if (!$best.hasClass("active")) { 71 | // .active is applied to the ToC link we're currently on, and its parent
      s selected by tocListSelector 72 | // .active-expanded is applied to the ToC links that are parents of this one 73 | $toc.find(".active").removeClass("active"); 74 | $toc.find(".active-parent").removeClass("active-parent"); 75 | $best.addClass("active"); 76 | $best.parents(tocListSelector).addClass("active").siblings(tocLinkSelector).addClass('active-parent'); 77 | $best.siblings(tocListSelector).addClass("active"); 78 | $toc.find(tocListSelector).filter(":not(.active)").slideUp(150); 79 | $toc.find(tocListSelector).filter(".active").slideDown(150); 80 | if (window.history.replaceState) { 81 | window.history.replaceState(null, "", best); 82 | } 83 | var thisTitle = $best.data("title") 84 | if (thisTitle !== undefined && thisTitle.length > 0) { 85 | document.title = thisTitle + " – " + originalTitle; 86 | } else { 87 | document.title = originalTitle; 88 | } 89 | } 90 | }; 91 | 92 | var makeToc = function() { 93 | recacheHeights(); 94 | refreshToc(); 95 | 96 | $("#nav-button").click(function() { 97 | $(".toc-wrapper").toggleClass('open'); 98 | $("#nav-button").toggleClass('open'); 99 | return false; 100 | }); 101 | $(".page-wrapper").click(closeToc); 102 | $(".toc-link").click(closeToc); 103 | 104 | // reload immediately after scrolling on toc click 105 | $toc.find(tocLinkSelector).click(function() { 106 | setTimeout(function() { 107 | refreshToc(); 108 | }, 0); 109 | }); 110 | 111 | $(window).scroll(debounce(refreshToc, 200)); 112 | $(window).resize(debounce(recacheHeights, 200)); 113 | }; 114 | 115 | makeToc(); 116 | 117 | window.recacheHeights = recacheHeights; 118 | window.refreshToc = refreshToc; 119 | } 120 | 121 | window.loadToc = loadToc; 122 | })(); 123 | -------------------------------------------------------------------------------- /slate/source/javascripts/lib/_energize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * energize.js v0.1.0 3 | * 4 | * Speeds up click events on mobile devices. 5 | * https://github.com/davidcalhoun/energize.js 6 | */ 7 | 8 | (function() { // Sandbox 9 | /** 10 | * Don't add to non-touch devices, which don't need to be sped up 11 | */ 12 | if(!('ontouchstart' in window)) return; 13 | 14 | var lastClick = {}, 15 | isThresholdReached, touchstart, touchmove, touchend, 16 | click, closest; 17 | 18 | /** 19 | * isThresholdReached 20 | * 21 | * Compare touchstart with touchend xy coordinates, 22 | * and only fire simulated click event if the coordinates 23 | * are nearby. (don't want clicking to be confused with a swipe) 24 | */ 25 | isThresholdReached = function(startXY, xy) { 26 | return Math.abs(startXY[0] - xy[0]) > 5 || Math.abs(startXY[1] - xy[1]) > 5; 27 | }; 28 | 29 | /** 30 | * touchstart 31 | * 32 | * Save xy coordinates when the user starts touching the screen 33 | */ 34 | touchstart = function(e) { 35 | this.startXY = [e.touches[0].clientX, e.touches[0].clientY]; 36 | this.threshold = false; 37 | }; 38 | 39 | /** 40 | * touchmove 41 | * 42 | * Check if the user is scrolling past the threshold. 43 | * Have to check here because touchend will not always fire 44 | * on some tested devices (Kindle Fire?) 45 | */ 46 | touchmove = function(e) { 47 | // NOOP if the threshold has already been reached 48 | if(this.threshold) return false; 49 | 50 | this.threshold = isThresholdReached(this.startXY, [e.touches[0].clientX, e.touches[0].clientY]); 51 | }; 52 | 53 | /** 54 | * touchend 55 | * 56 | * If the user didn't scroll past the threshold between 57 | * touchstart and touchend, fire a simulated click. 58 | * 59 | * (This will fire before a native click) 60 | */ 61 | touchend = function(e) { 62 | // Don't fire a click if the user scrolled past the threshold 63 | if(this.threshold || isThresholdReached(this.startXY, [e.changedTouches[0].clientX, e.changedTouches[0].clientY])) { 64 | return; 65 | } 66 | 67 | /** 68 | * Create and fire a click event on the target element 69 | * https://developer.mozilla.org/en/DOM/event.initMouseEvent 70 | */ 71 | var touch = e.changedTouches[0], 72 | evt = document.createEvent('MouseEvents'); 73 | evt.initMouseEvent('click', true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); 74 | evt.simulated = true; // distinguish from a normal (nonsimulated) click 75 | e.target.dispatchEvent(evt); 76 | }; 77 | 78 | /** 79 | * click 80 | * 81 | * Because we've already fired a click event in touchend, 82 | * we need to listed for all native click events here 83 | * and suppress them as necessary. 84 | */ 85 | click = function(e) { 86 | /** 87 | * Prevent ghost clicks by only allowing clicks we created 88 | * in the click event we fired (look for e.simulated) 89 | */ 90 | var time = Date.now(), 91 | timeDiff = time - lastClick.time, 92 | x = e.clientX, 93 | y = e.clientY, 94 | xyDiff = [Math.abs(lastClick.x - x), Math.abs(lastClick.y - y)], 95 | target = closest(e.target, 'A') || e.target, // needed for standalone apps 96 | nodeName = target.nodeName, 97 | isLink = nodeName === 'A', 98 | standAlone = window.navigator.standalone && isLink && e.target.getAttribute("href"); 99 | 100 | lastClick.time = time; 101 | lastClick.x = x; 102 | lastClick.y = y; 103 | 104 | /** 105 | * Unfortunately Android sometimes fires click events without touch events (seen on Kindle Fire), 106 | * so we have to add more logic to determine the time of the last click. Not perfect... 107 | * 108 | * Older, simpler check: if((!e.simulated) || standAlone) 109 | */ 110 | if((!e.simulated && (timeDiff < 500 || (timeDiff < 1500 && xyDiff[0] < 50 && xyDiff[1] < 50))) || standAlone) { 111 | e.preventDefault(); 112 | e.stopPropagation(); 113 | if(!standAlone) return false; 114 | } 115 | 116 | /** 117 | * Special logic for standalone web apps 118 | * See http://stackoverflow.com/questions/2898740/iphone-safari-web-app-opens-links-in-new-window 119 | */ 120 | if(standAlone) { 121 | window.location = target.getAttribute("href"); 122 | } 123 | 124 | /** 125 | * Add an energize-focus class to the targeted link (mimics :focus behavior) 126 | * TODO: test and/or remove? Does this work? 127 | */ 128 | if(!target || !target.classList) return; 129 | target.classList.add("energize-focus"); 130 | window.setTimeout(function(){ 131 | target.classList.remove("energize-focus"); 132 | }, 150); 133 | }; 134 | 135 | /** 136 | * closest 137 | * @param {HTMLElement} node current node to start searching from. 138 | * @param {string} tagName the (uppercase) name of the tag you're looking for. 139 | * 140 | * Find the closest ancestor tag of a given node. 141 | * 142 | * Starts at node and goes up the DOM tree looking for a 143 | * matching nodeName, continuing until hitting document.body 144 | */ 145 | closest = function(node, tagName){ 146 | var curNode = node; 147 | 148 | while(curNode !== document.body) { // go up the dom until we find the tag we're after 149 | if(!curNode || curNode.nodeName === tagName) { return curNode; } // found 150 | curNode = curNode.parentNode; // not found, so keep going up 151 | } 152 | 153 | return null; // not found 154 | }; 155 | 156 | /** 157 | * Add all delegated event listeners 158 | * 159 | * All the events we care about bubble up to document, 160 | * so we can take advantage of event delegation. 161 | * 162 | * Note: no need to wait for DOMContentLoaded here 163 | */ 164 | document.addEventListener('touchstart', touchstart, false); 165 | document.addEventListener('touchmove', touchmove, false); 166 | document.addEventListener('touchend', touchend, false); 167 | document.addEventListener('click', click, true); // TODO: why does this use capture? 168 | 169 | })(); -------------------------------------------------------------------------------- /slate/source/javascripts/lib/_imagesloaded.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * imagesLoaded PACKAGED v3.1.8 3 | * JavaScript is all like "You images are done yet or what?" 4 | * MIT License 5 | */ 6 | 7 | (function(){function e(){}function t(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var i=e.prototype,r=this,o=r.EventEmitter;i.getListeners=function(e){var t,n,i=this._getEvents();if("object"==typeof e){t={};for(n in i)i.hasOwnProperty(n)&&e.test(n)&&(t[n]=i[n])}else t=i[e]||(i[e]=[]);return t},i.flattenListeners=function(e){var t,n=[];for(t=0;e.length>t;t+=1)n.push(e[t].listener);return n},i.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},i.addListener=function(e,n){var i,r=this.getListenersAsObject(e),o="object"==typeof n;for(i in r)r.hasOwnProperty(i)&&-1===t(r[i],n)&&r[i].push(o?n:{listener:n,once:!1});return this},i.on=n("addListener"),i.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},i.once=n("addOnceListener"),i.defineEvent=function(e){return this.getListeners(e),this},i.defineEvents=function(e){for(var t=0;e.length>t;t+=1)this.defineEvent(e[t]);return this},i.removeListener=function(e,n){var i,r,o=this.getListenersAsObject(e);for(r in o)o.hasOwnProperty(r)&&(i=t(o[r],n),-1!==i&&o[r].splice(i,1));return this},i.off=n("removeListener"),i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,o=e?this.removeListener:this.addListener,s=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(i=n.length;i--;)o.call(this,t,n[i]);else for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?o.call(this,i,r):s.call(this,i,r));return this},i.removeEvent=function(e){var t,n=typeof e,i=this._getEvents();if("string"===n)delete i[e];else if("object"===n)for(t in i)i.hasOwnProperty(t)&&e.test(t)&&delete i[t];else delete this._events;return this},i.removeAllListeners=n("removeEvent"),i.emitEvent=function(e,t){var n,i,r,o,s=this.getListenersAsObject(e);for(r in s)if(s.hasOwnProperty(r))for(i=s[r].length;i--;)n=s[r][i],n.once===!0&&this.removeListener(e,n.listener),o=n.listener.apply(this,t||[]),o===this._getOnceReturnValue()&&this.removeListener(e,n.listener);return this},i.trigger=n("emitEvent"),i.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},i.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},i._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},i._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return r.EventEmitter=o,e},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return e}):"object"==typeof module&&module.exports?module.exports=e:this.EventEmitter=e}).call(this),function(e){function t(t){var n=e.event;return n.target=n.target||n.srcElement||t,n}var n=document.documentElement,i=function(){};n.addEventListener?i=function(e,t,n){e.addEventListener(t,n,!1)}:n.attachEvent&&(i=function(e,n,i){e[n+i]=i.handleEvent?function(){var n=t(e);i.handleEvent.call(i,n)}:function(){var n=t(e);i.call(e,n)},e.attachEvent("on"+n,e[n+i])});var r=function(){};n.removeEventListener?r=function(e,t,n){e.removeEventListener(t,n,!1)}:n.detachEvent&&(r=function(e,t,n){e.detachEvent("on"+t,e[t+n]);try{delete e[t+n]}catch(i){e[t+n]=void 0}});var o={bind:i,unbind:r};"function"==typeof define&&define.amd?define("eventie/eventie",o):e.eventie=o}(this),function(e,t){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(n,i){return t(e,n,i)}):"object"==typeof exports?module.exports=t(e,require("wolfy87-eventemitter"),require("eventie")):e.imagesLoaded=t(e,e.EventEmitter,e.eventie)}(window,function(e,t,n){function i(e,t){for(var n in t)e[n]=t[n];return e}function r(e){return"[object Array]"===d.call(e)}function o(e){var t=[];if(r(e))t=e;else if("number"==typeof e.length)for(var n=0,i=e.length;i>n;n++)t.push(e[n]);else t.push(e);return t}function s(e,t,n){if(!(this instanceof s))return new s(e,t);"string"==typeof e&&(e=document.querySelectorAll(e)),this.elements=o(e),this.options=i({},this.options),"function"==typeof t?n=t:i(this.options,t),n&&this.on("always",n),this.getImages(),a&&(this.jqDeferred=new a.Deferred);var r=this;setTimeout(function(){r.check()})}function f(e){this.img=e}function c(e){this.src=e,v[e]=this}var a=e.jQuery,u=e.console,h=u!==void 0,d=Object.prototype.toString;s.prototype=new t,s.prototype.options={},s.prototype.getImages=function(){this.images=[];for(var e=0,t=this.elements.length;t>e;e++){var n=this.elements[e];"IMG"===n.nodeName&&this.addImage(n);var i=n.nodeType;if(i&&(1===i||9===i||11===i))for(var r=n.querySelectorAll("img"),o=0,s=r.length;s>o;o++){var f=r[o];this.addImage(f)}}},s.prototype.addImage=function(e){var t=new f(e);this.images.push(t)},s.prototype.check=function(){function e(e,r){return t.options.debug&&h&&u.log("confirm",e,r),t.progress(e),n++,n===i&&t.complete(),!0}var t=this,n=0,i=this.images.length;if(this.hasAnyBroken=!1,!i)return this.complete(),void 0;for(var r=0;i>r;r++){var o=this.images[r];o.on("confirm",e),o.check()}},s.prototype.progress=function(e){this.hasAnyBroken=this.hasAnyBroken||!e.isLoaded;var t=this;setTimeout(function(){t.emit("progress",t,e),t.jqDeferred&&t.jqDeferred.notify&&t.jqDeferred.notify(t,e)})},s.prototype.complete=function(){var e=this.hasAnyBroken?"fail":"done";this.isComplete=!0;var t=this;setTimeout(function(){if(t.emit(e,t),t.emit("always",t),t.jqDeferred){var n=t.hasAnyBroken?"reject":"resolve";t.jqDeferred[n](t)}})},a&&(a.fn.imagesLoaded=function(e,t){var n=new s(this,e,t);return n.jqDeferred.promise(a(this))}),f.prototype=new t,f.prototype.check=function(){var e=v[this.img.src]||new c(this.img.src);if(e.isConfirmed)return this.confirm(e.isLoaded,"cached was confirmed"),void 0;if(this.img.complete&&void 0!==this.img.naturalWidth)return this.confirm(0!==this.img.naturalWidth,"naturalWidth"),void 0;var t=this;e.on("confirm",function(e,n){return t.confirm(e.isLoaded,n),!0}),e.check()},f.prototype.confirm=function(e,t){this.isLoaded=e,this.emit("confirm",this,t)};var v={};return c.prototype=new t,c.prototype.check=function(){if(!this.isChecked){var e=new Image;n.bind(e,"load",this),n.bind(e,"error",this),e.src=this.src,this.isChecked=!0}},c.prototype.handleEvent=function(e){var t="on"+e.type;this[t]&&this[t](e)},c.prototype.onload=function(e){this.confirm(!0,"onload"),this.unbindProxyEvents(e)},c.prototype.onerror=function(e){this.confirm(!1,"onerror"),this.unbindProxyEvents(e)},c.prototype.confirm=function(e,t){this.isConfirmed=!0,this.isLoaded=e,this.emit("confirm",this,t)},c.prototype.unbindProxyEvents=function(e){n.unbind(e.target,"load",this),n.unbind(e.target,"error",this)},s}); -------------------------------------------------------------------------------- /slate/source/javascripts/lib/_jquery.highlight.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Highlight plugin 3 | * 4 | * Based on highlight v3 by Johann Burkard 5 | * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html 6 | * 7 | * Code a little bit refactored and cleaned (in my humble opinion). 8 | * Most important changes: 9 | * - has an option to highlight only entire words (wordsOnly - false by default), 10 | * - has an option to be case sensitive (caseSensitive - false by default) 11 | * - highlight element tag and class names can be specified in options 12 | * 13 | * Usage: 14 | * // wrap every occurrance of text 'lorem' in content 15 | * // with (default options) 16 | * $('#content').highlight('lorem'); 17 | * 18 | * // search for and highlight more terms at once 19 | * // so you can save some time on traversing DOM 20 | * $('#content').highlight(['lorem', 'ipsum']); 21 | * $('#content').highlight('lorem ipsum'); 22 | * 23 | * // search only for entire word 'lorem' 24 | * $('#content').highlight('lorem', { wordsOnly: true }); 25 | * 26 | * // don't ignore case during search of term 'lorem' 27 | * $('#content').highlight('lorem', { caseSensitive: true }); 28 | * 29 | * // wrap every occurrance of term 'ipsum' in content 30 | * // with 31 | * $('#content').highlight('ipsum', { element: 'em', className: 'important' }); 32 | * 33 | * // remove default highlight 34 | * $('#content').unhighlight(); 35 | * 36 | * // remove custom highlight 37 | * $('#content').unhighlight({ element: 'em', className: 'important' }); 38 | * 39 | * 40 | * Copyright (c) 2009 Bartek Szopka 41 | * 42 | * Licensed under MIT license. 43 | * 44 | */ 45 | 46 | jQuery.extend({ 47 | highlight: function (node, re, nodeName, className) { 48 | if (node.nodeType === 3) { 49 | var match = node.data.match(re); 50 | if (match) { 51 | var highlight = document.createElement(nodeName || 'span'); 52 | highlight.className = className || 'highlight'; 53 | var wordNode = node.splitText(match.index); 54 | wordNode.splitText(match[0].length); 55 | var wordClone = wordNode.cloneNode(true); 56 | highlight.appendChild(wordClone); 57 | wordNode.parentNode.replaceChild(highlight, wordNode); 58 | return 1; //skip added node in parent 59 | } 60 | } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children 61 | !/(script|style)/i.test(node.tagName) && // ignore script and style nodes 62 | !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted 63 | for (var i = 0; i < node.childNodes.length; i++) { 64 | i += jQuery.highlight(node.childNodes[i], re, nodeName, className); 65 | } 66 | } 67 | return 0; 68 | } 69 | }); 70 | 71 | jQuery.fn.unhighlight = function (options) { 72 | var settings = { className: 'highlight', element: 'span' }; 73 | jQuery.extend(settings, options); 74 | 75 | return this.find(settings.element + "." + settings.className).each(function () { 76 | var parent = this.parentNode; 77 | parent.replaceChild(this.firstChild, this); 78 | parent.normalize(); 79 | }).end(); 80 | }; 81 | 82 | jQuery.fn.highlight = function (words, options) { 83 | var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false }; 84 | jQuery.extend(settings, options); 85 | 86 | if (words.constructor === String) { 87 | words = [words]; 88 | } 89 | words = jQuery.grep(words, function(word, i){ 90 | return word != ''; 91 | }); 92 | words = jQuery.map(words, function(word, i) { 93 | return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 94 | }); 95 | if (words.length == 0) { return this; }; 96 | 97 | var flag = settings.caseSensitive ? "" : "i"; 98 | var pattern = "(" + words.join("|") + ")"; 99 | if (settings.wordsOnly) { 100 | pattern = "\\b" + pattern + "\\b"; 101 | } 102 | var re = new RegExp(pattern, flag); 103 | 104 | return this.each(function () { 105 | jQuery.highlight(this, re, settings.element, settings.className); 106 | }); 107 | }; 108 | 109 | -------------------------------------------------------------------------------- /slate/source/layouts/layout.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright 2008-2013 Concur Technologies, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | not use this file except in compliance with the License. You may obtain 6 | a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations 14 | under the License. 15 | %> 16 | <% language_tabs = current_page.data.language_tabs || [] %> 17 | <% page_content = yield %> 18 | <% 19 | if current_page.data.includes 20 | current_page.data.includes.each do |include| 21 | page_content += partial("includes/#{include}") 22 | end 23 | end 24 | %> 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | <%= current_page.data.title || "API Documentation" %> 33 | <%= favicon_tag 'images/favicon.ico' %> 34 | 35 | 38 | <%= stylesheet_link_tag :screen, media: :screen %> 39 | <%= stylesheet_link_tag :print, media: :print %> 40 | <% if current_page.data.search %> 41 | <%= javascript_include_tag "all" %> 42 | <% else %> 43 | <%= javascript_include_tag "all_nosearch" %> 44 | <% end %> 45 | 46 | 47 | 48 | 49 | 50 | NAV 51 | <%= image_tag('navbar.png') %> 52 | 53 | 54 |
      55 | <%= image_tag "logo.png", class: 'logo' %> 56 | <% if language_tabs.any? %> 57 |
      58 | <% language_tabs.each do |lang| %> 59 | <% if lang.is_a? Hash %> 60 | <%= lang.values.first %> 61 | <% else %> 62 | <%= lang %> 63 | <% end %> 64 | <% end %> 65 |
      66 | <% end %> 67 | <% if current_page.data.search %> 68 | 71 |
        72 | <% end %> 73 |
          74 | <% toc_data(page_content).each do |h1| %> 75 |
        • 76 | <%= h1[:content] %> 77 | <% if h1[:children].length > 0 %> 78 | 85 | <% end %> 86 |
        • 87 | <% end %> 88 |
        89 | <% if current_page.data.toc_footers %> 90 | 95 | <% end %> 96 |
        97 |
        98 |
        99 |
        100 | <%= page_content %> 101 |
        102 |
        103 | <% if language_tabs.any? %> 104 |
        105 | <% language_tabs.each do |lang| %> 106 | <% if lang.is_a? Hash %> 107 | <%= lang.values.first %> 108 | <% else %> 109 | <%= lang %> 110 | <% end %> 111 | <% end %> 112 |
        113 | <% end %> 114 |
        115 |
        116 | 117 | 118 | -------------------------------------------------------------------------------- /slate/source/stylesheets/_icon-font.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'slate'; 3 | src:font-url('slate.eot?-syv14m'); 4 | src:font-url('slate.eot?#iefix-syv14m') format('embedded-opentype'), 5 | font-url('slate.woff2?-syv14m') format('woff2'), 6 | font-url('slate.woff?-syv14m') format('woff'), 7 | font-url('slate.ttf?-syv14m') format('truetype'), 8 | font-url('slate.svg?-syv14m#slate') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | %icon { 14 | font-family: 'slate'; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | } 22 | 23 | %icon-exclamation-sign { 24 | @extend %icon; 25 | content: "\e600"; 26 | } 27 | %icon-info-sign { 28 | @extend %icon; 29 | content: "\e602"; 30 | } 31 | %icon-ok-sign { 32 | @extend %icon; 33 | content: "\e606"; 34 | } 35 | %icon-search { 36 | @extend %icon; 37 | content: "\e607"; 38 | } 39 | -------------------------------------------------------------------------------- /slate/source/stylesheets/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | -------------------------------------------------------------------------------- /slate/source/stylesheets/_rtl.scss: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // RTL Styles Variables 3 | //////////////////////////////////////////////////////////////////////////////// 4 | 5 | $default: auto; 6 | 7 | //////////////////////////////////////////////////////////////////////////////// 8 | // TABLE OF CONTENTS 9 | //////////////////////////////////////////////////////////////////////////////// 10 | 11 | #toc>ul>li>a>span { 12 | float: left; 13 | } 14 | 15 | .toc-wrapper { 16 | transition: right 0.3s ease-in-out !important; 17 | left: $default !important; 18 | #{right}: 0; 19 | } 20 | 21 | .toc-h2 { 22 | padding-#{right}: $nav-padding + $nav-indent; 23 | } 24 | 25 | #nav-button { 26 | #{right}: 0; 27 | transition: right 0.3s ease-in-out; 28 | &.open { 29 | right: $nav-width 30 | } 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////// 34 | // PAGE LAYOUT AND CODE SAMPLE BACKGROUND 35 | //////////////////////////////////////////////////////////////////////////////// 36 | .page-wrapper { 37 | margin-#{left}: $default !important; 38 | margin-#{right}: $nav-width; 39 | .dark-box { 40 | #{right}: $default; 41 | #{left}: 0; 42 | } 43 | } 44 | 45 | .lang-selector { 46 | width: $default !important; 47 | a { 48 | float: right; 49 | } 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////// 53 | // CODE SAMPLE STYLES 54 | //////////////////////////////////////////////////////////////////////////////// 55 | .content { 56 | &>h1, 57 | &>h2, 58 | &>h3, 59 | &>h4, 60 | &>h5, 61 | &>h6, 62 | &>p, 63 | &>table, 64 | &>ul, 65 | &>ol, 66 | &>aside, 67 | &>dl { 68 | margin-#{left}: $examples-width; 69 | margin-#{right}: $default !important; 70 | } 71 | &>ul, 72 | &>ol { 73 | padding-#{right}: $main-padding + 15px; 74 | } 75 | table { 76 | th, 77 | td { 78 | text-align: right; 79 | } 80 | } 81 | dd { 82 | margin-#{right}: 15px; 83 | } 84 | aside { 85 | aside:before { 86 | padding-#{left}: 0.5em; 87 | } 88 | .search-highlight { 89 | background: linear-gradient(to top right, #F7E633 0%, #F1D32F 100%); 90 | } 91 | } 92 | pre, 93 | blockquote { 94 | float: left !important; 95 | clear: left !important; 96 | } 97 | } 98 | 99 | //////////////////////////////////////////////////////////////////////////////// 100 | // TYPOGRAPHY 101 | //////////////////////////////////////////////////////////////////////////////// 102 | h1, 103 | h2, 104 | h3, 105 | h4, 106 | h5, 107 | h6, 108 | p, 109 | aside { 110 | text-align: right; 111 | direction: rtl; 112 | } 113 | 114 | .toc-wrapper { 115 | text-align: right; 116 | direction: rtl; 117 | font-weight: 100 !important; 118 | } 119 | 120 | 121 | //////////////////////////////////////////////////////////////////////////////// 122 | // RESPONSIVE DESIGN 123 | //////////////////////////////////////////////////////////////////////////////// 124 | @media (max-width: $tablet-width) { 125 | .toc-wrapper { 126 | #{right}: -$nav-width; 127 | &.open { 128 | #{right}: 0; 129 | } 130 | } 131 | .page-wrapper { 132 | margin-#{right}: 0; 133 | } 134 | } 135 | 136 | @media (max-width: $phone-width) { 137 | %left-col { 138 | margin-#{left}: 0; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /slate/source/stylesheets/_variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2008-2013 Concur Technologies, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | not use this file except in compliance with the License. You may obtain 6 | a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations 14 | under the License. 15 | */ 16 | 17 | 18 | //////////////////////////////////////////////////////////////////////////////// 19 | // CUSTOMIZE SLATE 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // Use these settings to help adjust the appearance of Slate 22 | 23 | 24 | // BACKGROUND COLORS 25 | //////////////////// 26 | $nav-bg: #000000 !default; 27 | $examples-bg: #2E3336 !default; 28 | $code-bg: #1E2224 !default; 29 | $code-annotation-bg: #191D1F !default; 30 | $nav-subitem-bg: #1E2224 !default; 31 | $nav-active-bg: #00A9CE !default; 32 | $nav-active-parent-bg: #1E2224 !default; // parent links of the current section 33 | $lang-select-border: #000 !default; 34 | $lang-select-bg: #1E2224 !default; 35 | $lang-select-active-bg: $examples-bg !default; // feel free to change this to blue or something 36 | $lang-select-pressed-bg: #111 !default; // color of language tab bg when mouse is pressed 37 | $main-bg: #F3F7F9 !default; 38 | $aside-notice-bg: #8fbcd4 !default; 39 | $aside-warning-bg: #c97a7e !default; 40 | $aside-success-bg: #6ac174 !default; 41 | $search-notice-bg: #c97a7e !default; 42 | 43 | 44 | // TEXT COLORS 45 | //////////////////// 46 | $main-text: #333 !default; // main content text color 47 | $nav-text: #2FB787 !default; 48 | $nav-active-text: #fff !default; 49 | $nav-active-parent-text: #2FB787 !default; // parent links of the current section 50 | $lang-select-text: #fff !default; // color of unselected language tab text 51 | $lang-select-active-text: #fff !default; // color of selected language tab text 52 | $lang-select-pressed-text: #fff !default; // color of language tab text when mouse is pressed 53 | 54 | 55 | // SIZES 56 | //////////////////// 57 | $nav-width: 230px !default; // width of the navbar 58 | $examples-width: 40% !default; // portion of the screen taken up by code examples 59 | $logo-margin: 0px !default; // margin below logo 60 | $main-padding: 28px !default; // padding to left and right of content & examples 61 | $nav-padding: 15px !default; // padding to left and right of navbar 62 | $nav-v-padding: 10px !default; // padding used vertically around search boxes and results 63 | $nav-indent: 10px !default; // extra padding for ToC subitems 64 | $code-annotation-padding: 13px !default; // padding inside code annotations 65 | $h1-margin-bottom: 21px !default; // padding under the largest header tags 66 | $tablet-width: 930px !default; // min width before reverting to tablet size 67 | $phone-width: $tablet-width - $nav-width !default; // min width before reverting to mobile size 68 | 69 | 70 | // FONTS 71 | //////////////////// 72 | %default-font { 73 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 74 | font-size: 14px; 75 | } 76 | 77 | %header-font { 78 | @extend %default-font; 79 | font-weight: bold; 80 | } 81 | 82 | %code-font { 83 | font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; 84 | font-size: 12px; 85 | line-height: 1.5; 86 | } 87 | 88 | 89 | // OTHER 90 | //////////////////// 91 | $nav-footer-border-color: #666 !default; 92 | $search-box-border-color: #666 !default; 93 | 94 | 95 | //////////////////////////////////////////////////////////////////////////////// 96 | // INTERNAL 97 | //////////////////////////////////////////////////////////////////////////////// 98 | // These settings are probably best left alone. 99 | 100 | %break-words { 101 | word-break: break-all; 102 | hyphens: auto; 103 | } 104 | -------------------------------------------------------------------------------- /slate/source/stylesheets/print.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'variables'; 4 | @import 'icon-font'; 5 | 6 | /* 7 | Copyright 2008-2013 Concur Technologies, Inc. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); you may 10 | not use this file except in compliance with the License. You may obtain 11 | a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 18 | License for the specific language governing permissions and limitations 19 | under the License. 20 | */ 21 | 22 | $print-color: #999; 23 | $print-color-light: #ccc; 24 | $print-font-size: 12px; 25 | 26 | body { 27 | @extend %default-font; 28 | } 29 | 30 | .tocify, .toc-footer, .lang-selector, .search, #nav-button { 31 | display: none; 32 | } 33 | 34 | .tocify-wrapper>img { 35 | margin: 0 auto; 36 | display: block; 37 | } 38 | 39 | .logo { 40 | background-color: black; 41 | margin-bottom: 10px; 42 | width:100%; 43 | } 44 | 45 | .content { 46 | font-size: 12px; 47 | 48 | pre, code { 49 | @extend %code-font; 50 | @extend %break-words; 51 | border: 1px solid $print-color; 52 | border-radius: 5px; 53 | font-size: 0.8em; 54 | } 55 | 56 | pre { 57 | code { 58 | border: 0; 59 | } 60 | } 61 | 62 | pre { 63 | padding: 1.3em; 64 | } 65 | 66 | code { 67 | padding: 0.2em; 68 | } 69 | 70 | table { 71 | border: 1px solid $print-color; 72 | tr { 73 | border-bottom: 1px solid $print-color; 74 | } 75 | td,th { 76 | padding: 0.7em; 77 | } 78 | } 79 | 80 | p { 81 | line-height: 1.5; 82 | } 83 | 84 | a { 85 | text-decoration: none; 86 | color: #000; 87 | } 88 | 89 | h1 { 90 | @extend %header-font; 91 | font-size: 2.5em; 92 | padding-top: 0.5em; 93 | padding-bottom: 0.5em; 94 | margin-top: 1em; 95 | margin-bottom: $h1-margin-bottom; 96 | border: 2px solid $print-color-light; 97 | border-width: 2px 0; 98 | text-align: center; 99 | page-break-before: always; 100 | } 101 | 102 | h2 { 103 | @extend %header-font; 104 | font-size: 1.8em; 105 | margin-top: 2em; 106 | border-top: 2px solid $print-color-light; 107 | padding-top: 0.8em; 108 | } 109 | 110 | h1+h2, h1+div+h2 { 111 | border-top: none; 112 | padding-top: 0; 113 | margin-top: 0; 114 | } 115 | 116 | h3, h4 { 117 | @extend %header-font; 118 | font-size: 0.8em; 119 | margin-top: 1.5em; 120 | margin-bottom: 0.8em; 121 | text-transform: uppercase; 122 | } 123 | 124 | h5, h6 { 125 | text-transform: uppercase; 126 | } 127 | 128 | aside { 129 | padding: 1em; 130 | border: 1px solid $print-color-light; 131 | border-radius: 5px; 132 | margin-top: 1.5em; 133 | margin-bottom: 1.5em; 134 | line-height: 1.6; 135 | } 136 | 137 | aside:before { 138 | vertical-align: middle; 139 | padding-right: 0.5em; 140 | font-size: 14px; 141 | } 142 | 143 | aside.notice:before { 144 | @extend %icon-info-sign; 145 | } 146 | 147 | aside.warning:before { 148 | @extend %icon-exclamation-sign; 149 | } 150 | 151 | aside.success:before { 152 | @extend %icon-ok-sign; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /slate/source/stylesheets/screen.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'variables'; 4 | @import 'icon-font'; 5 | // @import 'rtl'; // uncomment to switch to RTL format 6 | 7 | /* 8 | Copyright 2008-2013 Concur Technologies, Inc. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); you may 11 | not use this file except in compliance with the License. You may obtain 12 | a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | License for the specific language governing permissions and limitations 20 | under the License. 21 | */ 22 | 23 | //////////////////////////////////////////////////////////////////////////////// 24 | // GENERAL STUFF 25 | //////////////////////////////////////////////////////////////////////////////// 26 | 27 | html, body { 28 | color: $main-text; 29 | padding: 0; 30 | margin: 0; 31 | -webkit-font-smoothing: antialiased; 32 | -moz-osx-font-smoothing: grayscale; 33 | @extend %default-font; 34 | background-color: $main-bg; 35 | height: 100%; 36 | -webkit-text-size-adjust: none; /* Never autoresize text */ 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////// 40 | // TABLE OF CONTENTS 41 | //////////////////////////////////////////////////////////////////////////////// 42 | 43 | #toc > ul > li > a > span { 44 | float: right; 45 | background-color: #2484FF; 46 | border-radius: 40px; 47 | width: 20px; 48 | } 49 | 50 | .toc-wrapper { 51 | transition: left 0.3s ease-in-out; 52 | 53 | overflow-y: auto; 54 | overflow-x: hidden; 55 | position: fixed; 56 | z-index: 30; 57 | top: 0; 58 | left: 0; 59 | bottom: 0; 60 | width: $nav-width; 61 | background-color: $nav-bg; 62 | font-size: 13px; 63 | font-weight: bold; 64 | 65 | // language selector for mobile devices 66 | .lang-selector { 67 | display: none; 68 | a { 69 | padding-top: 0.5em; 70 | padding-bottom: 0.5em; 71 | } 72 | } 73 | 74 | // This is the logo at the top of the ToC 75 | .logo { 76 | display: block; 77 | max-width: 100%; 78 | margin-bottom: $logo-margin; 79 | } 80 | 81 | &>.search { 82 | position: relative; 83 | 84 | input { 85 | background: $nav-bg; 86 | border-width: 0 0 1px 0; 87 | border-color: $search-box-border-color; 88 | padding: 6px 0 6px 20px; 89 | box-sizing: border-box; 90 | margin: $nav-v-padding $nav-padding; 91 | width: $nav-width - ($nav-padding*2); 92 | outline: none; 93 | color: $nav-text; 94 | border-radius: 0; /* ios has a default border radius */ 95 | } 96 | 97 | &:before { 98 | position: absolute; 99 | top: 17px; 100 | left: $nav-padding; 101 | color: $nav-text; 102 | @extend %icon-search; 103 | } 104 | } 105 | 106 | .search-results { 107 | margin-top: 0; 108 | box-sizing: border-box; 109 | height: 0; 110 | overflow-y: auto; 111 | overflow-x: hidden; 112 | transition-property: height, margin; 113 | transition-duration: 180ms; 114 | transition-timing-function: ease-in-out; 115 | background: $nav-subitem-bg; 116 | &.visible { 117 | height: 30%; 118 | margin-bottom: 1em; 119 | } 120 | 121 | li { 122 | margin: 1em $nav-padding; 123 | line-height: 1; 124 | } 125 | 126 | a { 127 | color: $nav-text; 128 | text-decoration: none; 129 | 130 | &:hover { 131 | text-decoration: underline; 132 | } 133 | } 134 | } 135 | 136 | 137 | // The Table of Contents is composed of multiple nested 138 | // unordered lists. These styles remove the default 139 | // styling of an unordered list because it is ugly. 140 | ul, li { 141 | list-style: none; 142 | margin: 0; 143 | padding: 0; 144 | line-height: 28px; 145 | } 146 | 147 | li { 148 | color: $nav-text; 149 | transition-property: background; 150 | transition-timing-function: linear; 151 | transition-duration: 200ms; 152 | } 153 | 154 | // This is the currently selected ToC entry 155 | .toc-link.active { 156 | background-color: $nav-active-bg; 157 | color: $nav-active-text; 158 | } 159 | 160 | // this is parent links of the currently selected ToC entry 161 | .toc-link.active-parent { 162 | background-color: $nav-active-parent-bg; 163 | color: $nav-active-parent-text; 164 | } 165 | 166 | .toc-list-h2 { 167 | display: none; 168 | background-color: $nav-subitem-bg; 169 | font-weight: 500; 170 | } 171 | 172 | .toc-h2 { 173 | padding-left: $nav-padding + $nav-indent; 174 | font-size: 12px; 175 | } 176 | 177 | .toc-footer { 178 | padding: 1em 0; 179 | margin-top: 1em; 180 | border-top: 1px dashed $nav-footer-border-color; 181 | 182 | li,a { 183 | color: $nav-text; 184 | text-decoration: none; 185 | } 186 | 187 | a:hover { 188 | text-decoration: underline; 189 | } 190 | 191 | li { 192 | font-size: 0.8em; 193 | line-height: 1.7; 194 | text-decoration: none; 195 | } 196 | } 197 | } 198 | 199 | .toc-link, .toc-footer li { 200 | padding: 0 $nav-padding 0 $nav-padding; 201 | display: block; 202 | overflow-x: hidden; 203 | white-space: nowrap; 204 | text-overflow: ellipsis; 205 | text-decoration: none; 206 | color: $nav-text; 207 | transition-property: background; 208 | transition-timing-function: linear; 209 | transition-duration: 130ms; 210 | } 211 | 212 | // button to show navigation on mobile devices 213 | #nav-button { 214 | span { 215 | display: block; 216 | $side-pad: $main-padding / 2 - 8px; 217 | padding: $side-pad $side-pad $side-pad; 218 | background-color: rgba($main-bg, 0.7); 219 | transform-origin: 0 0; 220 | transform: rotate(-90deg) translate(-100%, 0); 221 | border-radius: 0 0 0 5px; 222 | } 223 | padding: 0 1.5em 5em 0; // increase touch size area 224 | display: none; 225 | position: fixed; 226 | top: 0; 227 | left: 0; 228 | z-index: 100; 229 | color: #000; 230 | text-decoration: none; 231 | font-weight: bold; 232 | opacity: 0.7; 233 | line-height: 16px; 234 | img { 235 | height: 16px; 236 | vertical-align: bottom; 237 | } 238 | 239 | transition: left 0.3s ease-in-out; 240 | 241 | &:hover { opacity: 1; } 242 | &.open {left: $nav-width} 243 | } 244 | 245 | 246 | //////////////////////////////////////////////////////////////////////////////// 247 | // PAGE LAYOUT AND CODE SAMPLE BACKGROUND 248 | //////////////////////////////////////////////////////////////////////////////// 249 | 250 | .page-wrapper { 251 | margin-left: $nav-width; 252 | position: relative; 253 | z-index: 10; 254 | background-color: $main-bg; 255 | min-height: 100%; 256 | 257 | padding-bottom: 1px; // prevent margin overflow 258 | 259 | // The dark box is what gives the code samples their dark background. 260 | // It sits essentially under the actual content block, which has a 261 | // transparent background. 262 | // I know, it's hackish, but it's the simplist way to make the left 263 | // half of the content always this background color. 264 | .dark-box { 265 | width: $examples-width; 266 | background-color: $examples-bg; 267 | position: absolute; 268 | right: 0; 269 | top: 0; 270 | bottom: 0; 271 | } 272 | 273 | .lang-selector { 274 | position: fixed; 275 | z-index: 50; 276 | border-bottom: 5px solid $lang-select-active-bg; 277 | } 278 | } 279 | 280 | .lang-selector { 281 | background-color: $lang-select-bg; 282 | width: 100%; 283 | font-weight: bold; 284 | a { 285 | display: block; 286 | float:left; 287 | color: $lang-select-text; 288 | text-decoration: none; 289 | padding: 0 10px; 290 | line-height: 30px; 291 | outline: 0; 292 | 293 | &:active, &:focus { 294 | background-color: $lang-select-pressed-bg; 295 | color: $lang-select-pressed-text; 296 | } 297 | 298 | &.active { 299 | background-color: $lang-select-active-bg; 300 | color: $lang-select-active-text; 301 | } 302 | } 303 | 304 | &:after { 305 | content: ''; 306 | clear: both; 307 | display: block; 308 | } 309 | } 310 | 311 | //////////////////////////////////////////////////////////////////////////////// 312 | // CONTENT STYLES 313 | //////////////////////////////////////////////////////////////////////////////// 314 | // This is all the stuff with the light background in the left half of the page 315 | 316 | .content { 317 | // fixes webkit rendering bug for some: see #538 318 | -webkit-transform: translateZ(0); 319 | // to place content above the dark box 320 | position: relative; 321 | z-index: 30; 322 | 323 | &:after { 324 | content: ''; 325 | display: block; 326 | clear: both; 327 | } 328 | 329 | &>h1, &>h2, &>h3, &>h4, &>h5, &>h6, &>p, &>table, &>ul, &>ol, &>aside, &>dl { 330 | margin-right: $examples-width; 331 | padding: 0 $main-padding; 332 | box-sizing: border-box; 333 | display: block; 334 | 335 | @extend %left-col; 336 | } 337 | 338 | &>ul, &>ol { 339 | padding-left: $main-padding + 15px; 340 | } 341 | 342 | // the div is the tocify hidden div for placeholding stuff 343 | &>h1, &>h2, &>div { 344 | clear:both; 345 | } 346 | 347 | h1 { 348 | @extend %header-font; 349 | font-size: 25px; 350 | padding-top: 0.5em; 351 | padding-bottom: 0.5em; 352 | margin-bottom: $h1-margin-bottom; 353 | margin-top: 2em; 354 | border-top: 1px solid #ccc; 355 | border-bottom: 1px solid #ccc; 356 | background-color: #fdfdfd; 357 | } 358 | 359 | h1:first-child, div:first-child + h1 { 360 | border-top-width: 0; 361 | margin-top: 0; 362 | } 363 | 364 | h2 { 365 | @extend %header-font; 366 | font-size: 19px; 367 | margin-top: 4em; 368 | margin-bottom: 0; 369 | border-top: 1px solid #ccc; 370 | padding-top: 1.2em; 371 | padding-bottom: 1.2em; 372 | background-image: linear-gradient(to bottom, rgba(#fff, 0.2), rgba(#fff, 0)); 373 | } 374 | 375 | // h2s right after h1s should bump right up 376 | // against the h1s. 377 | h1 + h2, h1 + div + h2 { 378 | margin-top: $h1-margin-bottom * -1; 379 | border-top: none; 380 | } 381 | 382 | h3, h4, h5, h6 { 383 | @extend %header-font; 384 | font-size: 15px; 385 | margin-top: 2.5em; 386 | margin-bottom: 0.8em; 387 | } 388 | 389 | h4, h5, h6 { 390 | font-size: 14px; 391 | } 392 | 393 | hr { 394 | margin: 2em 0; 395 | border-top: 2px solid $examples-bg; 396 | border-bottom: 2px solid $main-bg; 397 | } 398 | 399 | table { 400 | margin-bottom: 1em; 401 | overflow: auto; 402 | th,td { 403 | text-align: left; 404 | vertical-align: top; 405 | line-height: 1.6; 406 | code { 407 | white-space: nowrap; 408 | } 409 | } 410 | 411 | th { 412 | padding: 5px 10px; 413 | border-bottom: 1px solid #ccc; 414 | vertical-align: bottom; 415 | } 416 | 417 | td { 418 | padding: 10px; 419 | } 420 | 421 | tr:last-child { 422 | border-bottom: 1px solid #ccc; 423 | } 424 | 425 | tr:nth-child(odd)>td { 426 | background-color: lighten($main-bg,4.2%); 427 | } 428 | 429 | tr:nth-child(even)>td { 430 | background-color: lighten($main-bg,2.4%); 431 | } 432 | } 433 | 434 | dt { 435 | font-weight: bold; 436 | } 437 | 438 | dd { 439 | margin-left: 15px; 440 | } 441 | 442 | p, li, dt, dd { 443 | line-height: 1.6; 444 | margin-top: 0; 445 | } 446 | 447 | img { 448 | max-width: 100%; 449 | } 450 | 451 | code { 452 | background-color: rgba(0,0,0,0.05); 453 | padding: 3px; 454 | border-radius: 3px; 455 | @extend %break-words; 456 | @extend %code-font; 457 | } 458 | 459 | pre>code { 460 | background-color: transparent; 461 | padding: 0; 462 | } 463 | 464 | aside { 465 | padding-top: 1em; 466 | padding-bottom: 1em; 467 | margin-top: 1.5em; 468 | margin-bottom: 1.5em; 469 | background: $aside-notice-bg; 470 | line-height: 1.6; 471 | 472 | &.warning { 473 | background-color: $aside-warning-bg; 474 | } 475 | 476 | &.success { 477 | background-color: $aside-success-bg; 478 | } 479 | } 480 | 481 | aside:before { 482 | vertical-align: middle; 483 | padding-right: 0.5em; 484 | font-size: 14px; 485 | } 486 | 487 | aside.notice:before { 488 | @extend %icon-info-sign; 489 | } 490 | 491 | aside.warning:before { 492 | @extend %icon-exclamation-sign; 493 | } 494 | 495 | aside.success:before { 496 | @extend %icon-ok-sign; 497 | } 498 | 499 | .search-highlight { 500 | padding: 2px; 501 | margin: -3px; 502 | border-radius: 4px; 503 | border: 1px solid #F7E633; 504 | background: linear-gradient(to top left, #F7E633 0%, #F1D32F 100%); 505 | } 506 | } 507 | 508 | //////////////////////////////////////////////////////////////////////////////// 509 | // CODE SAMPLE STYLES 510 | //////////////////////////////////////////////////////////////////////////////// 511 | // This is all the stuff that appears in the right half of the page 512 | 513 | .content { 514 | pre, blockquote { 515 | background-color: $code-bg; 516 | color: #fff; 517 | 518 | margin: 0; 519 | width: $examples-width; 520 | 521 | float:right; 522 | clear:right; 523 | 524 | box-sizing: border-box; 525 | 526 | @extend %right-col; 527 | 528 | &>p { margin: 0; } 529 | 530 | a { 531 | color: #fff; 532 | text-decoration: none; 533 | border-bottom: dashed 1px #ccc; 534 | } 535 | } 536 | 537 | pre { 538 | @extend %code-font; 539 | padding-top: 2em; 540 | padding-bottom: 2em; 541 | padding: 2em $main-padding; 542 | } 543 | 544 | blockquote { 545 | &>p { 546 | background-color: $code-annotation-bg; 547 | padding: $code-annotation-padding 2em; 548 | color: #eee; 549 | } 550 | } 551 | } 552 | 553 | //////////////////////////////////////////////////////////////////////////////// 554 | // RESPONSIVE DESIGN 555 | //////////////////////////////////////////////////////////////////////////////// 556 | // These are the styles for phones and tablets 557 | // There are also a couple styles disperesed 558 | 559 | @media (max-width: $tablet-width) { 560 | .toc-wrapper { 561 | left: -$nav-width; 562 | 563 | &.open { 564 | left: 0; 565 | } 566 | } 567 | 568 | .page-wrapper { 569 | margin-left: 0; 570 | } 571 | 572 | #nav-button { 573 | display: block; 574 | } 575 | 576 | .toc-link { 577 | padding-top: 0.3em; 578 | padding-bottom: 0.3em; 579 | } 580 | } 581 | 582 | @media (max-width: $phone-width) { 583 | .dark-box { 584 | display: none; 585 | } 586 | 587 | %left-col { 588 | margin-right: 0; 589 | } 590 | 591 | .toc-wrapper .lang-selector { 592 | display: block; 593 | } 594 | 595 | .page-wrapper .lang-selector { 596 | display: none; 597 | } 598 | 599 | %right-col { 600 | width: auto; 601 | float: none; 602 | } 603 | 604 | %right-col + %left-col { 605 | margin-top: $main-padding; 606 | } 607 | } 608 | 609 | .highlight .c, .highlight .cm, .highlight .c1, .highlight .cs { 610 | color: #909090; 611 | } 612 | 613 | .highlight, .highlight .w { 614 | background-color: $code-bg; 615 | } 616 | -------------------------------------------------------------------------------- /workshops/InfoSecWorkshop06122018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/workshops/InfoSecWorkshop06122018.pdf -------------------------------------------------------------------------------- /workshops/InfoSecWorkshop16112018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsumerDataStandardsAustralia/infosec/1524fc8a727e64ccc39cb2a26a47ed3d0e132c41/workshops/InfoSecWorkshop16112018.pdf --------------------------------------------------------------------------------