Full Code of NUWCDIVNPT/stig-manager for AI

main b21da06cca79 cached
613 files
25.8 MB
6.8M tokens
1301 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (27,174K chars total). Download the full file to get everything.
Repository: NUWCDIVNPT/stig-manager
Branch: main
Commit: b21da06cca79
Files: 613
Total size: 25.8 MB

Directory structure:
gitextract_d5fz8a2i/

├── .dockerignore
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report-form.yml
│   │   └── feature_request.md
│   └── workflows/
│       ├── api-audit-test-coverage-response.yml
│       ├── api-binary-tests.yml
│       ├── api-container-tests.yml
│       ├── api-spec-validation.yml
│       ├── api-state-tests.yml
│       ├── build-binary-artifacts.yml
│       ├── build-client.yml
│       ├── build-docs.yml
│       ├── client-sonarcloud.yml
│       ├── pub-docker.yml
│       └── unit-tests.yml
├── .readthedocs.yml
├── CONTRIBUTING.md
├── CONTRIBUTORS.md
├── Dockerfile
├── INTENT.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── api/
│   ├── README.md
│   ├── bin/
│   │   └── .gitignore
│   ├── build.sh
│   ├── dist/
│   │   └── .gitignore
│   ├── launchers/
│   │   ├── gen-launchers.py
│   │   ├── stig-manager.bat
│   │   └── stig-manager.sh
│   ├── nuwcdivnpt-bot.gpg.asc
│   ├── pkg.config.json
│   └── source/
│       ├── README.md
│       ├── bootstrap/
│       │   ├── bootstrapUtils.js
│       │   ├── client.js
│       │   ├── dependencies.js
│       │   ├── docs.js
│       │   ├── errorHandlers.js
│       │   ├── extensionCheck.js
│       │   ├── middlewares.js
│       │   ├── server.js
│       │   └── signals.js
│       ├── controllers/
│       │   ├── Asset.js
│       │   ├── Collection.js
│       │   ├── Job.js
│       │   ├── Metrics.js
│       │   ├── Operation.js
│       │   ├── Review.js
│       │   ├── STIG.js
│       │   └── User.js
│       ├── healthcheck.js
│       ├── index.js
│       ├── package.json
│       ├── service/
│       │   ├── AssetService.js
│       │   ├── CollectionService.js
│       │   ├── JobService.js
│       │   ├── MetricsService.js
│       │   ├── OperationService.js
│       │   ├── ReviewService.js
│       │   ├── STIGService.js
│       │   ├── UserService.js
│       │   ├── migrations/
│       │   │   ├── 0000.js
│       │   │   ├── 0001.js
│       │   │   ├── 0002.js
│       │   │   ├── 0003.js
│       │   │   ├── 0004.js
│       │   │   ├── 0005.js
│       │   │   ├── 0006.js
│       │   │   ├── 0007.js
│       │   │   ├── 0008.js
│       │   │   ├── 0009.js
│       │   │   ├── 0010.js
│       │   │   ├── 0011.js
│       │   │   ├── 0012.js
│       │   │   ├── 0013.js
│       │   │   ├── 0014.js
│       │   │   ├── 0015.js
│       │   │   ├── 0016.js
│       │   │   ├── 0017.js
│       │   │   ├── 0018.js
│       │   │   ├── 0019.js
│       │   │   ├── 0020.js
│       │   │   ├── 0021.js
│       │   │   ├── 0022.js
│       │   │   ├── 0023.js
│       │   │   ├── 0024.js
│       │   │   ├── 0025.js
│       │   │   ├── 0026.js
│       │   │   ├── 0027.js
│       │   │   ├── 0028.js
│       │   │   ├── 0029.js
│       │   │   ├── 0032.js
│       │   │   ├── 0033.js
│       │   │   ├── 0034.js
│       │   │   ├── 0035.js
│       │   │   ├── 0036.js
│       │   │   ├── 0037.js
│       │   │   ├── 0038.js
│       │   │   ├── 0039.js
│       │   │   ├── 0040.js
│       │   │   ├── 0041.js
│       │   │   ├── 0042.js
│       │   │   ├── 0043.js
│       │   │   ├── 0044.js
│       │   │   ├── 0045.js
│       │   │   ├── 0046.js
│       │   │   ├── lib/
│       │   │   │   ├── MigrationHandler.js
│       │   │   │   ├── mysql-import.js
│       │   │   │   └── umzug-mysql-storage.js
│       │   │   └── sql/
│       │   │       ├── 0000/
│       │   │       │   └── up/
│       │   │       │       ├── 10-stigman-schema.sql
│       │   │       │       ├── 31-stigman-static.sql
│       │   │       │       └── 32-cci-data.sql
│       │   │       ├── 0001/
│       │   │       │   ├── down/
│       │   │       │   │   └── 10-collection-created.sql
│       │   │       │   └── up/
│       │   │       │       └── 10-collection-created.sql
│       │   │       ├── 0002/
│       │   │       │   ├── down/
│       │   │       │   │   └── 10-collection-description.sql
│       │   │       │   └── up/
│       │   │       │       └── 10-collection-description.sql
│       │   │       ├── 0003/
│       │   │       │   └── up/
│       │   │       │       └── 10-asset-mac-fqdn.sql
│       │   │       ├── 0004/
│       │   │       │   └── up/
│       │   │       │       └── 10-user-data.sql
│       │   │       ├── 0005/
│       │   │       │   ├── down/
│       │   │       │   │   └── 10-v-current-rev.sql
│       │   │       │   └── up/
│       │   │       │       └── 10-v-current-rev.sql
│       │   │       ├── 0006/
│       │   │       │   └── up/
│       │   │       │       └── 10-v-current-rev.sql
│       │   │       ├── current/
│       │   │       │   ├── 10-stigman-tables.sql
│       │   │       │   ├── 20-stigman-static.sql
│       │   │       │   └── 31-rev5-cci-data.sql
│       │   │       └── generateSchema.sh
│       │   └── utils.js
│       ├── specification/
│       │   ├── log-socket.yaml
│       │   └── stig-manager.yaml
│       ├── tls/
│       │   └── README.md
│       └── utils/
│           ├── PoolMonitor.js
│           ├── asyncApiValidator.js
│           ├── auth.js
│           ├── buffer-json.js
│           ├── config.js
│           ├── error.js
│           ├── escape.js
│           ├── jwksCache.js
│           ├── klona.js
│           ├── log-schema.json
│           ├── logSocket.js
│           ├── logger.js
│           ├── parsers.js
│           ├── poam-template-mccast.xlsx
│           ├── poam-template.xlsx
│           ├── roles.js
│           ├── serializeError.js
│           ├── serializers.js
│           ├── state.js
│           ├── writer.js
│           └── xlsx-template-js-zip-upgrade/
│               ├── LICENSE
│               ├── README.md
│               ├── lib/
│               │   ├── index.d.ts
│               │   └── index.js
│               └── package.json
├── client/
│   ├── README.md
│   ├── build.sh
│   ├── dist/
│   │   └── .gitignore
│   └── src/
│       ├── css/
│       │   ├── ColumnHeaderGroup.css
│       │   ├── RowEditor.css
│       │   ├── dark-mode.css
│       │   ├── init.css
│       │   ├── jsonview.bundle.css
│       │   └── stigman.css
│       ├── ext/
│       │   ├── INCLUDE_ORDER.txt
│       │   ├── adapter/
│       │   │   └── ext/
│       │   │       ├── ext-base-debug.js
│       │   │       └── ext-base.js
│       │   ├── ext-all-debug-w-comments.js
│       │   ├── ext-all-debug.js
│       │   ├── ext-all.js
│       │   ├── ext.jsb2
│       │   ├── gpl-3.0.txt
│       │   ├── index.html
│       │   ├── license.txt
│       │   ├── release-notes.html
│       │   ├── resources/
│       │   │   ├── charts.swf
│       │   │   ├── css/
│       │   │   │   ├── debug.css
│       │   │   │   ├── ext-all-notheme.css
│       │   │   │   ├── ext-all.css
│       │   │   │   ├── reset-min.css
│       │   │   │   ├── structure/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel-reset.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── pivotgrid.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── reset.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── theme-access/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── theme-gray/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── pivotgrid.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── visual/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── pivotgrid.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── xtheme-access.css
│       │   │   │   ├── xtheme-blue.css
│       │   │   │   ├── xtheme-gray.css
│       │   │   │   └── yourtheme.css
│       │   │   ├── expressinstall.swf
│       │   │   └── images/
│       │   │       ├── access/
│       │   │       │   └── form/
│       │   │       │       ├── clear-trigger.psd
│       │   │       │       ├── date-trigger.psd
│       │   │       │       ├── search-trigger.psd
│       │   │       │       └── trigger.psd
│       │   │       ├── default/
│       │   │       │   ├── form/
│       │   │       │   │   ├── clear-trigger.psd
│       │   │       │   │   ├── date-trigger.psd
│       │   │       │   │   ├── search-trigger.psd
│       │   │       │   │   ├── trigger-square.psd
│       │   │       │   │   └── trigger.psd
│       │   │       │   └── window/
│       │   │       │       ├── left-corners.psd
│       │   │       │       ├── left-right.psd
│       │   │       │       ├── right-corners.psd
│       │   │       │       └── top-bottom.psd
│       │   │       └── yourtheme/
│       │   │           ├── README.txt
│       │   │           ├── form/
│       │   │           │   ├── clear-trigger.psd
│       │   │           │   ├── date-trigger.psd
│       │   │           │   ├── search-trigger.psd
│       │   │           │   ├── trigger-square.psd
│       │   │           │   └── trigger.psd
│       │   │           └── window/
│       │   │               ├── left-corners.psd
│       │   │               ├── left-right.psd
│       │   │               ├── right-corners.psd
│       │   │               └── top-bottom.psd
│       │   └── ux/
│       │       ├── BufferView.js
│       │       ├── CenterLayout.js
│       │       ├── CheckColumn.js
│       │       ├── ColumnHeaderGroup.js
│       │       ├── ColumnNodeUI.js
│       │       ├── DataView-more.js
│       │       ├── DataViewTransition.js
│       │       ├── FieldLabeler.js
│       │       ├── FieldReplicator.js
│       │       ├── Focus.js
│       │       ├── GMapPanel.js
│       │       ├── GroupSummary.js
│       │       ├── GroupTab.js
│       │       ├── GroupTabPanel.js
│       │       ├── ItemSelector.js
│       │       ├── LockingGridView.js
│       │       ├── MultiSelect.js
│       │       ├── PagingMemoryProxy.js
│       │       ├── PanelResizer.js
│       │       ├── Portal.js
│       │       ├── PortalColumn.js
│       │       ├── Portlet.js
│       │       ├── ProgressBarPager.js
│       │       ├── Reorderer.js
│       │       ├── RowEditor.js
│       │       ├── RowExpander.js
│       │       ├── RowLayout.js
│       │       ├── SearchField.js
│       │       ├── SelectBox.js
│       │       ├── SlidingPager.js
│       │       ├── Spinner.js
│       │       ├── SpinnerField.js
│       │       ├── Spotlight.js
│       │       ├── TabCloseMenu.js
│       │       ├── TabScrollerMenu.js
│       │       ├── TableGrid.js
│       │       ├── ToolbarDroppable.js
│       │       ├── ToolbarReorderer.js
│       │       ├── XmlTreeLoader.js
│       │       ├── css/
│       │       │   ├── CenterLayout.css
│       │       │   ├── ColumnHeaderGroup.css
│       │       │   ├── ColumnNodeUI.css
│       │       │   ├── GroupSummary.css
│       │       │   ├── GroupTab.css
│       │       │   ├── LockingGridView.css
│       │       │   ├── MultiSelect.css
│       │       │   ├── PanelResizer.css
│       │       │   ├── Portal.css
│       │       │   ├── RowEditor.css
│       │       │   ├── Spinner.css
│       │       │   └── ux-all.css
│       │       ├── fileuploadfield/
│       │       │   ├── FileUploadField.js
│       │       │   └── css/
│       │       │       └── fileuploadfield.css
│       │       ├── gridfilters/
│       │       │   ├── GridFilters.js
│       │       │   ├── css/
│       │       │   │   ├── GridFilters.css
│       │       │   │   └── RangeMenu.css
│       │       │   ├── filter/
│       │       │   │   ├── BooleanFilter.js
│       │       │   │   ├── DateFilter.js
│       │       │   │   ├── Filter.js
│       │       │   │   ├── ListFilter.js
│       │       │   │   ├── NumericFilter.js
│       │       │   │   └── StringFilter.js
│       │       │   └── menu/
│       │       │       ├── ListMenu.js
│       │       │       └── RangeMenu.js
│       │       ├── statusbar/
│       │       │   ├── StatusBar.js
│       │       │   ├── ValidationStatus.js
│       │       │   └── css/
│       │       │       └── statusbar.css
│       │       ├── treegrid/
│       │       │   ├── TreeGrid.js
│       │       │   ├── TreeGridColumnResizer.js
│       │       │   ├── TreeGridColumns.js
│       │       │   ├── TreeGridLoader.js
│       │       │   ├── TreeGridNodeUI.js
│       │       │   ├── TreeGridSorter.js
│       │       │   └── treegrid.css
│       │       ├── ux-all-debug.js
│       │       └── ux-all.js
│       ├── index.html
│       ├── js/
│       │   ├── BufferView.js
│       │   ├── ColumnHeaderGroup.js
│       │   ├── Env.js.example
│       │   ├── ExportButton.js
│       │   ├── FileSaver.js
│       │   ├── FileUploadField.js
│       │   ├── LockingGridView.js
│       │   ├── MessageBox.js
│       │   ├── RowEditor.js
│       │   ├── RowExpander.js
│       │   ├── SM/
│       │   │   ├── Acl.js
│       │   │   ├── ActivityHandler.js
│       │   │   ├── Ajax.js
│       │   │   ├── ApiState.js
│       │   │   ├── AppData.js
│       │   │   ├── AppInfo.js
│       │   │   ├── AssetSelection.js
│       │   │   ├── Attachments.js
│       │   │   ├── BatchReview.js
│       │   │   ├── Cache.js
│       │   │   ├── Checklist.js
│       │   │   ├── Classification.js
│       │   │   ├── CollectionClone.js
│       │   │   ├── CollectionPanel.js
│       │   │   ├── ColumnFilters.js
│       │   │   ├── Error.js
│       │   │   ├── EventDispatcher.js
│       │   │   ├── Exports.js
│       │   │   ├── FindingsPanel.js
│       │   │   ├── FlexboxLayout.js
│       │   │   ├── Global.js
│       │   │   ├── Grant.js
│       │   │   ├── Inventory.js
│       │   │   ├── Job.js
│       │   │   ├── Library.js
│       │   │   ├── LogStream.js
│       │   │   ├── MainPanel.js
│       │   │   ├── Manage.js
│       │   │   ├── MetaPanel.js
│       │   │   ├── NavTree.js
│       │   │   ├── Review.js
│       │   │   ├── ReviewsImport.js
│       │   │   ├── RowEditorToolbar.js
│       │   │   ├── SelectingGridToolbar.js
│       │   │   ├── ServiceWorker.js
│       │   │   ├── StackTrace.js
│       │   │   ├── State.js
│       │   │   ├── StigRevision.js
│       │   │   ├── TipContent.js
│       │   │   ├── TransferAssets.js
│       │   │   ├── User.js
│       │   │   ├── UserGroup.js
│       │   │   └── WhatsNew.js
│       │   ├── collectionAdmin.js
│       │   ├── collectionManager.js
│       │   ├── collectionReview.js
│       │   ├── completionStatus.js
│       │   ├── diff.js
│       │   ├── findingsSummary.js
│       │   ├── init.js
│       │   ├── jsonview.bundle.js
│       │   ├── library.js
│       │   ├── modules/
│       │   │   ├── package.json
│       │   │   └── source-map/
│       │   │       ├── mappings.wasm
│       │   │       └── source-map.js
│       │   ├── overrides.js
│       │   ├── resources-dist.js
│       │   ├── resources.js
│       │   ├── review.js
│       │   ├── stigAdmin.js
│       │   ├── stigman.js
│       │   ├── stigmanUtils.js
│       │   └── workers/
│       │       ├── oidc-worker.js
│       │       ├── service-worker.js
│       │       └── state-worker.js
│       └── reauth.html
├── data/
│   ├── appdata/
│   │   └── README.md
│   └── schemas/
│       ├── Stigman-Model.mwb
│       └── _manifest.json
├── docker-build.sh
├── docs/
│   ├── .nojekyll
│   ├── Dockerfile
│   ├── Makefile
│   ├── STIG-Manager-OSS.ckl
│   ├── _build/
│   │   ├── .gitignore
│   │   └── html/
│   │       └── .gitignore
│   ├── _static/
│   │   └── css/
│   │       ├── custom-pydata-theme.css
│   │       └── custom.css
│   ├── admin-guide/
│   │   ├── admin-guide.rst
│   │   ├── admin-quickstart.rst
│   │   └── index.rst
│   ├── build.sh
│   ├── conf.py
│   ├── features/
│   │   ├── common-tasks.rst
│   │   └── index.rst
│   ├── index.html
│   ├── index.rst
│   ├── installation-and-setup/
│   │   ├── authentication.rst
│   │   ├── data-and-permissions.rst
│   │   ├── db.rst
│   │   ├── environment-variables.rst
│   │   ├── envvars-node.csv
│   │   ├── envvars.csv
│   │   ├── index.rst
│   │   ├── installation-and-setup.rst
│   │   ├── logging.rst
│   │   ├── reverse-proxy.rst
│   │   ├── securing.rst
│   │   └── stigman-asd-full.csv
│   ├── make.bat
│   ├── reference/
│   │   └── index.rst
│   ├── requirements.txt
│   ├── the-project/
│   │   ├── DockerHub_Readme.md
│   │   ├── clients.rst
│   │   ├── contributing.rst
│   │   ├── documentation.rst
│   │   ├── examples.rst
│   │   ├── index.rst
│   │   ├── project-description.rst
│   │   ├── related-repos.rst
│   │   ├── requirements-and-dependencies.rst
│   │   └── testing.rst
│   └── user-guide/
│       ├── Stig-Manager-Asset-Batch-Import.csv
│       ├── index.rst
│       ├── republished-rules.csv
│       ├── review-handling.rst
│       ├── roles-and-access.rst
│       ├── rule-exceptions.rst
│       ├── user-guide.rst
│       └── user-quickstart.rst
├── release-notes.rst
├── root.json
└── test/
    ├── api/
    │   ├── README.md
    │   ├── appdata/
    │   │   ├── appdata-meta-metrics-with-pin.jsonl
    │   │   ├── appdata.jsonl
    │   │   ├── batch-test-data.jsonl
    │   │   ├── user-status-get-post.jsonl
    │   │   └── user-status-patch-put.jsonl
    │   ├── dark.css
    │   ├── form-data-files/
    │   │   ├── U_MS_Windows_10_STIG_V1R23_Manual-xccdf.xml
    │   │   ├── U_RHEL_7_STIG_V3R0-3_Manual-xccdf.xml
    │   │   ├── U_VPN_SRG-OTHER_V1R1_Manual-xccdf.xml
    │   │   ├── U_VPN_SRG-OTHER_V1R1_twoRules-matchingFingerprints.xml
    │   │   ├── U_VPN_SRG_V1R0_Manual-xccdf.xml
    │   │   ├── U_VPN_SRG_V1R1_Manual-xccdf-replace.xml
    │   │   ├── U_VPN_SRG_V1R1_Manual-xccdf.xml
    │   │   └── U_VPN_SRG_V2R3_Manual-xccdf-reviewKeyChange.xml
    │   ├── mocha/
    │   │   ├── cross-boundary/
    │   │   │   └── lvl1.test.js
    │   │   ├── data/
    │   │   │   ├── acl/
    │   │   │   │   ├── directAcl.test.js
    │   │   │   │   ├── directIterations.js
    │   │   │   │   ├── groupAcl.test.js
    │   │   │   │   ├── groupIterations.js
    │   │   │   │   └── referenceData.js
    │   │   │   ├── asset/
    │   │   │   │   ├── assetDelete.test.js
    │   │   │   │   ├── assetGet.test.js
    │   │   │   │   ├── assetPatch.test.js
    │   │   │   │   ├── assetPost.test.js
    │   │   │   │   ├── assetPut.test.js
    │   │   │   │   ├── expectations.js
    │   │   │   │   └── requestBodies.js
    │   │   │   ├── collection/
    │   │   │   │   ├── collectionDelete.test.js
    │   │   │   │   ├── collectionGet.test.js
    │   │   │   │   ├── collectionPatch.test.js
    │   │   │   │   ├── collectionPost.test.js
    │   │   │   │   ├── collectionPut.test.js
    │   │   │   │   ├── expectations.js
    │   │   │   │   └── requestBodies.js
    │   │   │   ├── metrics/
    │   │   │   │   ├── expectations.js
    │   │   │   │   ├── metaMetricsGet.json
    │   │   │   │   ├── metaMetricsGet.test.js
    │   │   │   │   ├── metricsGet.json
    │   │   │   │   └── metricsGet.test.js
    │   │   │   ├── operation/
    │   │   │   │   └── op.test.js
    │   │   │   ├── review/
    │   │   │   │   ├── expectations.js
    │   │   │   │   ├── requestBodies.js
    │   │   │   │   ├── reviewDelete.test.js
    │   │   │   │   ├── reviewGet.test.js
    │   │   │   │   ├── reviewPatch.test.js
    │   │   │   │   ├── reviewPost.test.js
    │   │   │   │   └── reviewPut.test.js
    │   │   │   ├── stig/
    │   │   │   │   ├── expectations.js
    │   │   │   │   └── stigs.test.js
    │   │   │   ├── user/
    │   │   │   │   ├── expectations.js
    │   │   │   │   ├── requestBodies.js
    │   │   │   │   └── user.test.js
    │   │   │   └── user-group/
    │   │   │       ├── requestBodies.js
    │   │   │       └── user-group.test.js
    │   │   ├── integration/
    │   │   │   ├── access.test.js
    │   │   │   ├── aclResolution.test.js
    │   │   │   ├── asset.test.js
    │   │   │   ├── collection.test.js
    │   │   │   ├── deleteHandling.test.js
    │   │   │   ├── expectations.js
    │   │   │   ├── grantChange.test.js
    │   │   │   ├── job.test.js
    │   │   │   ├── logStream.test.js
    │   │   │   ├── metrics.test.js
    │   │   │   ├── resultEngine.test.js
    │   │   │   ├── review.test.js
    │   │   │   ├── revisionPinning.test.js
    │   │   │   ├── roleResolution.test.js
    │   │   │   ├── stig.test.js
    │   │   │   └── userStatus.test.js
    │   │   ├── iterations.js
    │   │   ├── referenceData.js
    │   │   ├── security/
    │   │   │   └── reviewCrossCollectionWrite.test.js
    │   │   ├── testConfig.js
    │   │   └── utils/
    │   │       └── testUtils.js
    │   ├── mock-keycloak/
    │   │   └── auth/
    │   │       └── realms/
    │   │           └── stigman/
    │   │               ├── .well-known/
    │   │               │   └── openid-configuration
    │   │               └── protocol/
    │   │                   └── openid-connect/
    │   │                       └── certs
    │   ├── mock-keycloak-test-cases/
    │   │   ├── no-jwks/
    │   │   │   └── auth/
    │   │   │       └── realms/
    │   │   │           └── stigman/
    │   │   │               ├── .well-known/
    │   │   │               │   └── openid-configuration
    │   │   │               └── protocol/
    │   │   │                   └── openid-connect/
    │   │   │                       └── certs
    │   │   └── secure-kid/
    │   │       └── auth/
    │   │           └── realms/
    │   │               └── stigman/
    │   │                   ├── .well-known/
    │   │                   │   └── openid-configuration
    │   │                   └── protocol/
    │   │                       └── openid-connect/
    │   │                           └── certs
    │   ├── package.json
    │   └── runMocha.sh
    ├── state/
    │   ├── drop-db.sh
    │   ├── mocha/
    │   │   ├── bootstrap.test.js
    │   │   ├── db.test.js
    │   │   ├── jwks.test.js
    │   │   ├── lib.js
    │   │   ├── oidc.test.js
    │   │   └── tokenValidation.test.js
    │   └── package.json
    ├── unit/
    │   ├── mocha/
    │   │   └── asyncApiValidator.test.js
    │   └── package.json
    └── utils/
        ├── appdata-update.js
        ├── mockOidc.js
        └── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
**/node_modules
**/state.json
**/README.md
**/.git
**/.gitignore
**/data
**/test
**/uploads
**/docker
!client/**/node_modules


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report-form.yml
================================================
name: 🐞 Bug Report
description: File a bug/issue
title: "***The title of your Issue here***"
labels: [Bug, Needs Triage]
body:
- type: checkboxes
  attributes:
    label: Is there an existing issue for this?
    description: Please search to see if an issue already exists for the bug you encountered.
    options:
    - label: I have searched the existing issues
      required: true
- type: checkboxes
  attributes:
    label: Are you using the latest version of STIG Manager?
    description: The latest release is ![GitHub release](https://img.shields.io/github/v/release/NUWCDIVNPT/stig-manager?label=%20). You can see the version you are using in the app on the Home tab, in the badge next to the STIG Manager name and logo. The STIGMan project is in development using an agile process that releases new features and bugfixes frequently. 
    options:
      - label: I am using the latest [Release](https://github.com/NUWCDIVNPT/stig-manager/releases).
      - label: I am NOT using the latest [Release](https://github.com/NUWCDIVNPT/stig-manager/releases). I am aware that the first thing I will be asked to do is update the application so that I have the latest bugfixes. 
- type: checkboxes
  id: issue-location
  attributes:
    label: Where are you experiencing the issue?
    description: Select one or more.
    options:
     - label: API
     -  label: UI or other client
     -  label: Deployment
     -  label: Elsewhere
- type: textarea
  attributes:
    label: Current Behavior
    description: A description of what you're experiencing.
  validations:
    required: true
- type: textarea
  attributes:
    label: Expected Behavior
    description: A description of what you expected to happen.
  validations:
    required: false
- type: textarea
  attributes:
    label: Steps To Reproduce
    description: Steps to reproduce the behavior.
    placeholder: |
      1. In this environment...
      2. With this config...
      3. Run '...'
      4. See error...
  validations:
    required: false
- type: textarea
  attributes:
    label: Can you provide screenshots, logs, or other useful artifacts?
    description: |
      Links? References? Anything that will give us more context about the issue you are encountering!

      Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
  validations:
    required: false
- type: textarea
  attributes:
    label: Describe your Environment
    description: |
      examples:
        - **Hosting**: Are you hosting your own deployment of STIGMan or being provided with an instance? 
        - **Browser**: Chrome
        - **OS**: Ubuntu 20.04
        - **Node**: 13.14.0
        - **npm**: 7.6.3
    value: |
        - Hosting:
        - Browser:
        - OS:
        - Node:
        - npm:
    render: markdown
  validations:
    required: false    


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: 'FEATURE REQUEST: '
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/api-audit-test-coverage-response.yml
================================================
name: API source
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
      - test-coverage
    paths:
      - "api/source/**"
      - "test/api/**"
      - ".github/workflows/api-audit-test-coverage-response.yml"

  push:
    branches:
      - main
      - test-coverage
    paths:
      - "api/source/**"
      - "test/api/**"
      - ".github/workflows/api-audit-test-coverage-response.yml"

env:
  STIGMAN_API_PORT: 64001
  STIGMAN_DB_HOST: localhost
  STIGMAN_DB_PORT: 3306
  STIGMAN_DB_PASSWORD: stigman
  STIGMAN_API_AUTHORITY: http://127.0.0.1:8080/auth/realms/stigman
  STIGMAN_SWAGGER_ENABLED: true
  STIGMAN_SWAGGER_SERVER: http://localhost:64001/api
  STIGMAN_SWAGGER_REDIRECT: http://localhost:64001/api-docs/oauth2-redirect.html
  STIGMAN_DEV_RESPONSE_VALIDATION: logOnly
  STIGMAN_EXPERIMENTAL_APPDATA: 'true'
  STIGMAN_DEV_ALLOW_INSECURE_TOKENS: 'true'

  NODE_V8_COVERAGE: /home/runner/work/stig-manager/stig-manager/api/source/coverage/tmp/

permissions:
  pull-requests: read # allows SonarCloud to decorate PRs with analysis results

jobs:
  npm_audit:
    name: npm audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: install dependencies
        run: npm ci
        working-directory: ./api/source/
      - name: Audit Dependencies and Create PR Comment if needed
        uses: oke-py/npm-audit-action@2c6b2da234031fbf72af81a04c76b3a152bb2222 # pin@v2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          create_issues: false
          create_pr_comments: true
          working_directory: ./api/source/
  test_api:
    name: Run tests with coverage
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - name: coverage directory
        run: printenv NODE_V8_COVERAGE
      - name: Install app dependencies
        working-directory: ./api/source
        run: npm ci
      - name: Install test dependencies
        run: npm ci
        working-directory: ./test/api/
      - name: Install utils test dependencies
        run: npm ci
        working-directory: ./test/utils/
      - name: Run mock Keycloak
        id: idp-run
        working-directory: ./test/api/mock-keycloak
        run: |
          python3 -m http.server 8080 &
      - name: Run MySQL container
        id: mysql-run
        run: |
          docker run -d --name stig-manager-db \
          -p 3306:3306 \
          -e MYSQL_ROOT_PASSWORD=rootpw \
          -e MYSQL_DATABASE=stigman \
          -e MYSQL_USER=stigman \
          -e MYSQL_PASSWORD=stigman \
          mysql:8.0.24
      - name: Install c8 coverage reporter
        run: |
          sudo npm install -g c8
      - name: Run app and echo pid
        working-directory: ./api/source
        run: sh -c 'echo $$ > /tmp/test.pid ; exec c8 -r html node index.js > api-log.json 2>&1' &
      - name: pid file check
        working-directory: ./api/source
        run: cat /tmp/test.pid
      - name: Wait for bootstrap
        run: for i in {1..10}; do [ $i -gt 1 ] && sleep 5; curl --output /dev/null --silent --fail http://localhost:64001/api/op/configuration && s=0 && break || s=$?; printf '.'; done; (exit $s)
      - name: Run tests with coverage
        working-directory: ./test/api/
        run: npm test
      - name: Upload mocha test report
        id: artifact-upload-mocha
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: mocha-report
          path: ./test/api/mochawesome-report
      - name: Kill child pid
        working-directory: ./api/source
        run: kill -SIGINT $(ps -ef --ppid `cat /tmp/test.pid` -o pid= )
      - name: Wait until c8 process ends, or 60 seconds, whichever is shorter.
        run: timeout 60 tail --pid=`cat /tmp/test.pid` -f /dev/null
      - name: run c8 text/lcov report
        working-directory: ./api/source
        run: c8 report -r lcov -r text -r html
      - name: Upload coverage artifact
        id: artifact-upload-coverage
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: coverage-report
          path: ./api/source/coverage
      - name: Upload API logs
        id: artifact-upload-api-logs
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: api-log
          path: ./api/source/api-log.json
  response_validation:
    name: Response validation
    needs:
      - test_api
    runs-on: ubuntu-latest
    steps:
      - name: Download API log artifact
        uses: actions/download-artifact@v4
        with:
          name: api-log
          path: ./logs
      - name: Test for response validation messages
        working-directory: ./logs
        run: |
          jq -s 'map(select(.type=="responseValidation")|{method:.data.request.method,url:.data.request.url,errors:.data.error.errors,body:.data.body})' api-log.json > response-validation.json
          exit $(jq '. | length' response-validation.json)
      - name: Upload response validation artifact
        if: ${{ failure() }}
        uses: actions/upload-artifact@v4
        with:
          name: response-validation
          path: ./logs/response-validation.json
  SonarCloudAnalysis-API:
    name: SonarCloud Analysis
    needs: test_api
    runs-on: ubuntu-latest
    steps:
      - name: Check if PR is from a fork
        id: check_fork
        run: |
          if [ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]; then
            echo "This is a PR from a fork, skipping sonarcloud analysis."
            echo "SKIP_STEP=true" >> $GITHUB_ENV
          fi
      - name: Checkout repository
        if: env.SKIP_STEP != 'true'
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Important to fetch all history for accurate blame information
      - name: Download lcov artifact
        if: env.SKIP_STEP != 'true'
        uses: actions/download-artifact@v4
        with:
          name: coverage-report
      - name: Move lcov.info to api/source
        if: env.SKIP_STEP != 'true'
        run: mv lcov.info ./api/source/

      - name: Analyze API with SonarCloud
        if: env.SKIP_STEP != 'true'
        uses: SonarSource/sonarqube-scan-action@v6.0.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_API }} # Needed to push to SonarCloud
        with:
          # Additional arguments for the sonarcloud scanner
          projectBaseDir: ./api/source
          args: -Dsonar.projectKey=nuwcdivnpt_stig-manager-api
            -Dsonar.projectName=nuwcdivnpt_stig-manager-api
            -Dsonar.organization=nuwcdivnpt
            -Dsonar.inclusions=**/*.js
            -Dsonar.exclusions=**/node_modules/**,**/coverage-report/**
            -Dsonar.javascript.lcov.reportPaths=./lcov.info

    #   This will fail the action if Quality Gate fails (leaving out for now )
    #  - name: Check Quality Gate
    #    uses: sonarsource/sonarqube-quality-gate-action@master
    #    env:
    #      SONAR_TOKEN:


================================================
FILE: .github/workflows/api-binary-tests.yml
================================================

name: Build and Test Linux Binary
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - "api/source/**"
      - "test/api/**"
      - ".github/workflows/api-binary-tests.yml"
      - "api/build.sh"
      - "client/build.sh"
      - "docs/build.sh"

  push:
    branches:
      - main
    paths:
      - "api/source/**"
      - "test/api/**"
      - ".github/workflows/api-binary-tests.yml"
      - "api/build.sh"
      - "client/build.sh"
      - "docs/build.sh"

      
env:
  STIGMAN_API_PORT: 64001
  STIGMAN_DB_HOST: localhost
  STIGMAN_DB_PORT: 3306
  STIGMAN_DB_PASSWORD: stigman
  STIGMAN_API_AUTHORITY: http://127.0.0.1:8080/auth/realms/stigman
  STIGMAN_SWAGGER_ENABLED: true
  STIGMAN_SWAGGER_SERVER: http://127.0.0.1:64001/api
  STIGMAN_SWAGGER_REDIRECT: http://127.0.0.1:64001/api-docs/oauth2-redirect.html
  STIGMAN_DEV_RESPONSE_VALIDATION: logOnly
  STIGMAN_EXPERIMENTAL_APPDATA: 'true'
  STIGMAN_OIDC_PROVIDER: http://127.0.0.1:8080/auth/realms/stigman
  STIGMAN_DEV_ALLOW_INSECURE_TOKENS: 'true'
jobs:
  build-artifacts:
    name: Build binary artifacts
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*

      - name: Get repository metadata
        id: repo
        uses: actions/github-script@v7
        with:
          script: |
            const repo = await github.rest.repos.get(context.repo)
            return repo.data     

      - name: install uglify
        run: |
          sudo npm install -g uglify-js    

      - name: run build script
        id: run-the-build-script
        working-directory: ./api
        run: ./build.sh

      - name: Upload builds
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: binary-artifacts
          path: ./api/bin/
          if-no-files-found: error

      - name: Upload archives
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: binary-archives
          path: ./api/dist/
          if-no-files-found: error

  run-test-linux-binary-artifact:
    name: Run and test linux artifact
    needs: build-artifacts
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*

      - name: Run mock Keycloak
        id: idp-run
        working-directory: test/api/mock-keycloak
        run: |
          python3 -m http.server 8080 &

      - name: Run MySQL container
        id: mysql-run
        run: |
          docker run -d --name stig-manager-db \
          -p 3306:3306 \
          -e MYSQL_ROOT_PASSWORD=rootpw \
          -e MYSQL_DATABASE=stigman \
          -e MYSQL_USER=stigman \
          -e MYSQL_PASSWORD=stigman \
          mysql:8.0.24
      - name: wait 10 seconds
        run: sleep 10

      - name: Download builds
        uses: actions/download-artifact@v4
        with:
          name: binary-artifacts  
          path: ./binary-artifacts

      - name: Set execute permissions on binary
        run: chmod +x ./binary-artifacts/stig-manager-linuxstatic
      
      - name: Run linux binary and log output
        working-directory: ./
        run: |
          mkdir -p ./binary-artifacts/logs
          echo "Running tests on binary artifacts"
          ./binary-artifacts/stig-manager-linuxstatic > ./binary-artifacts/logs/output.log 2>&1 &
          echo $! > binary-artifacts/stig-manager.pid

      - name: Wait for bootstrap
        run: for i in {1..10}; do [ $i -gt 1 ] && sleep 5; curl --output /dev/null --silent --fail http://localhost:64001/api/op/configuration && s=0 && break || s=$?; printf '.'; done; (exit $s)
          
      - name: Install test dependencies
        run: npm ci
        working-directory: ./test/api/
      - name: Install utils test dependencies
        run: npm ci
        working-directory: ./test/utils/
      - name: Run tests with coverage and log output
        working-directory: ./test/api/
        run: |
          set -o pipefail
          npm test 2>&1 | tee ../../binary-artifacts/logs/test-output.log

      - name: Stop linux binary
        if: always()
        run: |
          if [ -f binary-artifacts/stig-manager.pid ]; then
            kill $(cat binary-artifacts/stig-manager.pid) || true
          fi

      - name: Upload logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-logs
          path: ./binary-artifacts/logs/

================================================
FILE: .github/workflows/api-container-tests.yml
================================================
name: API containers
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - "api/source/**"
      - "test/api/**"
      - "Dockerfile"
      - ".github/workflows/api-container-tests.yml"

jobs:
  fetch-mysql-versions:
    runs-on: ubuntu-latest
    outputs:
      MYSQL_VERSIONS: ${{ steps.fetch-versions.outputs.version_array }}
    steps:
      - name: Fetch MySQL Versions
        id: fetch-versions
        run: |
          # Fetch latest 3 MySQL 8.0.x versions plus 8.0.24
          MYSQL_8_0=$(curl -s "https://registry.hub.docker.com/v2/repositories/library/mysql/tags/?page_size=100" | jq -r '.results[].name | select(test("^8\\.0\\.\\d+$"))' | sort -V | tail -n2 | cat <(echo "8.0.24") - | sort -V | uniq)
          
          # Fetch latest 2 MySQL 8.4.x versions
          MYSQL_8_4=$(curl -s "https://registry.hub.docker.com/v2/repositories/library/mysql/tags/?page_size=100" | jq -r '.results[].name | select(test("^8\\.4\\.\\d+$"))' | sort -V | tail -n2)
          
          # Combine both version lists into JSON array
          VERSIONS=$(echo "$MYSQL_8_0" "$MYSQL_8_4" | tr ' ' '\n' | jq -Rnc '[inputs]')
          echo "version_array=$VERSIONS" >> $GITHUB_OUTPUT

  test_api:
    needs: fetch-mysql-versions
    name: ${{ matrix.container.name }} and MySQL ${{ matrix.mysql_version }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        container:
            - name: "stig-manager-alpine"
              build_arg: "node:lts-alpine"
        mysql_version: ${{fromJson(needs.fetch-mysql-versions.outputs.MYSQL_VERSIONS)}}
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - name: Build image for ${{ matrix.container.name }}
        id: image-build
        run: |
          docker build -t ${{ matrix.container.name }} --build-arg BASE_IMAGE=${{ matrix.container.build_arg }} .
      - name: Run mock Keycloak
        id: id-run
        working-directory: ./test/api/mock-keycloak
        run: |
          python3 -m http.server 8080 &
      - name: Run MySQL container version ${{ matrix.mysql_version }}
        id: mysql-run
        run: |
          docker run -d --name stig-manager-db \
          -p 3306:3306 \
          -e MYSQL_ROOT_PASSWORD=rootpw \
          -e MYSQL_DATABASE=stigman \
          -e MYSQL_USER=stigman \
          -e MYSQL_PASSWORD=stigman \
          mysql:${{ matrix.mysql_version }}
      - name: Run STIG Manager container ${{ matrix.container.name }}
        id: api-run
        run: |
          docker run -d --name stig-manager-api \
          --net=host \
          -e STIGMAN_API_PORT=64001 \
          -e STIGMAN_DB_HOST=localhost \
          -e STIGMAN_DB_PORT=3306 \
          -e STIGMAN_DB_PASSWORD=stigman \
          -e STIGMAN_API_AUTHORITY=http://127.0.0.1:8080/auth/realms/stigman \
          -e STIGMAN_DEV_RESPONSE_VALIDATION=logOnly \
          -e STIGMAN_EXPERIMENTAL_APPDATA=true \
          -e STIGMAN_DEV_ALLOW_INSECURE_TOKENS=true \
          ${{ matrix.container.name }}

      - name: Install test dependencies
        run: npm ci
        working-directory: ./test/api/
      - name: Install utils test dependencies
        run: npm ci
        working-directory: ./test/utils/

      - name: Wait for bootstrap
        run: for i in {1..10}; do [ $i -gt 1 ] && sleep 5; curl --output /dev/null --silent --fail http://localhost:64001/api/op/configuration && s=0 && break || s=$?; printf '.'; done; (exit $s)
      - name: Run tests with coverage
        working-directory: ./test/api/
        run: npm test
      - name: Upload mocha test report
        id: artifact-upload-mocha
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: mocha-report-${{ matrix.container.name }}-${{ matrix.mysql_version }}
          path: ./test/api/mochawesome-report
   
      - name: Extract API container log
        id: api-log-extract
        if: ${{ always() }}
        working-directory: ./test/api
        run: |
          docker logs stig-manager-api > api-log-${{ matrix.container.name }}-${{ matrix.mysql_version }}-${{ github.run_id }}.json
      - name: Upload API log artifact
        uses: actions/upload-artifact@v4
        id: api-log-upload
        if: ${{ always() }}
        with:
          name: api-log-${{ matrix.container.name }}-${{ matrix.mysql_version }}-${{ github.run_id }}
          path: ./test/api/api-log-${{ matrix.container.name }}-${{ matrix.mysql_version }}-${{ github.run_id }}.json
      - name: Collect all container logs on failure
        if: ${{ cancelled() || failure() }}
        uses: jwalton/gh-docker-logs@54a2a89cd6a2c929525f26ca67a7a4857a5dc1d9 # pin@v1
        with:
          dest: "./logs-${{ matrix.container.name }}-${{ matrix.mysql_version }}"
      - name: Tar container logs
        if: ${{ cancelled() || failure() }}
        run: tar cvzf ./logs-${{ matrix.container.name }}-${{ matrix.mysql_version }}.tgz ./logs-${{ matrix.container.name }}-${{ matrix.mysql_version }}
      - name: Upload container logs artifact
        if: ${{ cancelled() || failure() }}
        uses: actions/upload-artifact@v4
        with:
          name: logs-${{ matrix.container.name }}-${{ matrix.mysql_version }}.tgz
          path: ./logs-${{ matrix.container.name }}-${{ matrix.mysql_version }}.tgz
      


================================================
FILE: .github/workflows/api-spec-validation.yml
================================================
name: API spec validation
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - "api/source/specification/**"
      - ".github/workflows/api-spec-validation.yml"
  push:
    branches:
      - main
    paths:
      - "api/source/specification/**"
      - ".github/workflows/api-spec-validation.yml"

jobs:
  validate_asyncapi:
    name: Validate AsyncAPI specs
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - name: Validate log-socket.yaml
        run: npx --yes @asyncapi/cli@2 validate api/source/specification/log-socket.yaml


================================================
FILE: .github/workflows/api-state-tests.yml
================================================
name: API state tests
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - "api/source/**"
      - "test/state/**"
      - ".github/workflows/api-state-tests.yml"
jobs:
  api-state-tests:
    name: state tests
    runs-on: ubuntu-latest
    strategy:
      matrix: 
        component: ["bootstrap", "db", "jwks", "oidc", "tokenValidation"]
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
      - name: Install api libraries
        working-directory: ./api/source
        run: npm ci
      - name: Install Test dependencies
        working-directory: ./test/state
        run: npm ci
      - name: Install Test utils dependencies
        working-directory: ./test/utils
        run: npm ci
      - name: Run tests
        working-directory: ./test/state
        run: npx mocha --reporter mochawesome --showFailed --exit './mocha/${{ matrix.component}}.test.js'
      - name: Upload mocha test report
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: mocha-report-${{ matrix.component}}
          path: ./test/state/mochawesome-report



================================================
FILE: .github/workflows/build-binary-artifacts.yml
================================================

name: Build Binary Artifacts and Sign
on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - 'api/source/**'
      - 'client/src/**'
      - 'client/build.sh'
      - 'docs/**'
      - '.github/workflows/build-client.yml'
      - '.github/workflows/build-docs.yml'
      - '.github/workflows/build-binary-artifacts.yml'
    tags:
      - 1.**
jobs:
  build-binary-artifacts-and-sign:
    name: Build binary artifacts, sign, export
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
        with:
          ref: main
          fetch-depth: 0

      - name: Get repository metadata
        id: repo
        uses: actions/github-script@v7
        with:
          script: |
            const repo = await github.rest.repos.get(context.repo)
            return repo.data     

      - name: install uglify
        run: |
          sudo npm install -g uglify-js    

      - name: run build script
        id: run-the-build-script
        working-directory: ./api
        run: ./build.sh

      - name: Import GPG Key
        id: import_gpg
        run: | 
          if ! echo "${{ secrets.STIGMAN_PRIVATE_KEY }}" | gpg --import; then
            echo "::warning ::Private key GPG Import failed"
            exit 1
          fi

      - name: Get latest tag
        id: get_tag
        run: |
          DESCRIBE=$(git describe --tags | sed 's/\(.*\)-.*/\1/')
          echo "tag=$DESCRIBE" >> $GITHUB_ENV

      - name: Sign Dist Artifacts
        id: sign_artifacts
        working-directory: ./api/dist
        run: |
        
         if ! gpg --default-key nuwcdivnpt-bot@users.noreply.github.com --armor --detach-sig ./stig-manager-linux-${{ env.tag }}.tar.xz; then
            echo "::warning ::Linux Signing failed"
            exit 1
          fi
         if ! gpg --default-key nuwcdivnpt-bot@users.noreply.github.com --armor --detach-sig ./stig-manager-win-${{ env.tag }}.zip; then
            echo "::warning ::Windows Signing failed"
            exit 1
         fi
        
      - name: Verify Signatures
        id: verify_signatures
        working-directory: ./api/dist
        run: |
          if ! gpg --verify stig-manager-linux-${{ env.tag }}.tar.xz.asc stig-manager-linux-${{ env.tag }}.tar.xz; then
            echo "::warning ::Signature verification for Linux failed"
            exit 1
          fi
          if ! gpg --verify stig-manager-win-${{ env.tag }}.zip.asc stig-manager-win-${{ env.tag }}.zip; then
            echo "::warning ::Signature verification for Windows failed"
            exit 1
          fi
   
      - name: Upload builds
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: binary-artifacts
          path: ./api/bin/
          if-no-files-found: error

      - name: Upload archives
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: binary-archives
          path: ./api/dist/
          if-no-files-found: error

================================================
FILE: .github/workflows/build-client.yml
================================================
name: Build client
on:
  workflow_dispatch:
  workflow_call:
jobs:
  builder:
    name: builder
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
      - name: Install uglify-js
        run: npm install -g uglify-js
      - name: Create distribution
        working-directory: ./client
        run: ./build.sh
      - name: Upload distribution
        uses: actions/upload-artifact@v4
        with:
          name: client-dist
          path: ./client/dist


================================================
FILE: .github/workflows/build-docs.yml
================================================
name: Build docs
on:
  workflow_dispatch:
  workflow_call:
jobs:
  builder:
    name: builder
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
      - name: run image, generating docs
        working-directory: ./docs
        run: ./build.sh
      - name: Upload docs
        uses: actions/upload-artifact@v4
        with:
          name: docs-build
          path: ./docs/_build/html


================================================
FILE: .github/workflows/client-sonarcloud.yml
================================================
name: Client SonarCloud
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - "client/src/js/**"
      - "client/src/css/**"
      - "client/src/serviceWorker.js"
      - ".github/workflows/client-sonarcloud.yml"

  push:
    branches:
      - main
    paths:
      - "client/src/js/**"
      - "client/src/css/**"
      - "client/src/serviceWorker.js"
      - ".github/workflows/client-sonarcloud.yml"

permissions:
  pull-requests: read # allows SonarCloud to decorate PRs with analysis results

jobs:
  SonarCloudAnalysis-Client:
    name: SonarCloud Analysis client
    runs-on: ubuntu-latest
    steps:
      - name: Check if PR is from a fork
        id: check_fork
        run: |
          if [ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]; then
            echo "This is a PR from a fork, skipping sonarcloud analysis."
            echo "SKIP_STEP=true" >> $GITHUB_ENV
          fi
      #checkout the repo
      - name: Checkout repository
        if: env.SKIP_STEP != 'true'
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Important to fetch all history for accurate blame information
      
      - name: Analyze client with SonarCloud
        if: env.SKIP_STEP != 'true'
        uses: SonarSource/sonarqube-scan-action@v6.0.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_CLIENT }} # Needed to push to SonarCloud
        with:
          projectBaseDir: ./client/src
          # Additional arguments for the sonarcloud scanner
          args: -Dsonar.projectKey=nuwcdivnpt_stig-manager-client
            -Dsonar.projectName=nuwcdivnpt_stig-manager-client
            -Dsonar.organization=nuwcdivnpt
            -Dsonar.inclusions=**/*.js,**/*.html,**/*.css
            -Dsonar.exclusions=**/node_modules/**

    #   This will fail the action if Quality Gate fails (leaving out for now )
    #  - name: Check Quality Gate
    #    uses: sonarsource/sonarqube-quality-gate-action@master
    #    env:
    #      SONAR_TOKEN:


================================================
FILE: .github/workflows/pub-docker.yml
================================================
name: Publish Docker images
env:
  DOCKERHUB_REPOSITORY: nuwcdivnpt/stig-manager
on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - 'api/source/**'
      - 'client/src/**'
      - 'client/build.sh'
      - 'docs/**'
      - 'Dockerfile'
      - '.github/workflows/build-client.yml'
      - '.github/workflows/build-docs.yml'
      - '.github/workflows/pub-docker.yml'
    tags:
      - 1.**
jobs:
  build-client:
    uses: nuwcdivnpt/stig-manager/.github/workflows/build-client.yml@main
  build-docs:
    uses: nuwcdivnpt/stig-manager/.github/workflows/build-docs.yml@main
  build-push-alpine:
    name: Build and push from Alpine base
    needs:
      - build-client
      - build-docs
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4
        with:
          ref: main
          fetch-depth: 0
      - name: Download client distribution
        uses: actions/download-artifact@v4
        with:
          name: client-dist
          path: ./client/dist
      - name: Download documentation
        uses: actions/download-artifact@v4
        with:
          name: docs-build
          path: ./docs/_build/html
      - name: Get repository metadata
        id: repo
        uses: actions/github-script@v7
        with:
          script: |
            const repo = await github.rest.repos.get(context.repo)
            return repo.data
      - name: Prepare variables
        id: prep
        run: |
          DOCKER_IMAGE=${{ env.DOCKERHUB_REPOSITORY }}
          BRANCH=$(git symbolic-ref --short HEAD)
          SHA=$(git rev-parse --short=10 HEAD)
          DESCRIBE=$(git describe --tags)
          TAG=$(git describe --tags --abbrev=0)
          TAGS=${DOCKER_IMAGE}:latest
          [[ ${{ github.ref_type }} == "tag" ]] && TAGS="$TAGS,${DOCKER_IMAGE}:${{ github.ref_name }}" 
          [[ ${{ github.event_name }} == "workflow_dispatch" && ${{ github.ref_name }} != "main" ]] && TAGS="${DOCKER_IMAGE}:${{ github.ref_name }}"
          echo "version=${TAG}" >> $GITHUB_OUTPUT
          echo "sha=${SHA}" >> $GITHUB_OUTPUT
          echo "tag=${TAG}" >> $GITHUB_OUTPUT
          echo "branch=${BRANCH}" >> $GITHUB_OUTPUT
          echo "tags=${TAGS}" >> $GITHUB_OUTPUT
          echo "describe=${DESCRIBE}" >> $GITHUB_OUTPUT
          echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # pin@v2
      - name: Login to DockerHub
        uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # pin@v2
        with:
          username: ${{ secrets.DOCKERHUB_ORG_OWNER_USERNAME }}
          password: ${{ secrets.DOCKERHUB_ORG_OWNER_PW }}
      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # pin@v3
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          file: ./Dockerfile
          push: true
          build-args: |
            COMMIT_BRANCH=${{ steps.prep.outputs.branch }}
            COMMIT_SHA=${{ steps.prep.outputs.sha }}
            COMMIT_TAG=${{ steps.prep.outputs.tag }}
            COMMIT_DESCRIBE=${{ steps.prep.outputs.describe }}
          tags: ${{ steps.prep.outputs.tags }}
          labels: |
            org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
            org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
            org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
            org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
            org.opencontainers.image.version=${{ steps.prep.outputs.version }}
            org.opencontainers.image.created=${{ steps.prep.outputs.created }}
            org.opencontainers.image.revision=${{ steps.prep.outputs.describe }}
            org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
      - name: Image digest
        run: echo ${{ steps.docker_build.outputs.digest }}
      - name: Update Docker Hub Description
        if: github.event_name != 'workflow_dispatch'
        uses: peter-evans/dockerhub-description@202973a37c8a723405c0c5f0a71b6d99db470dae # pin@v3
        with:
          username: ${{ secrets.DOCKERHUB_ORG_OWNER_USERNAME }}
          password: ${{ secrets.DOCKERHUB_ORG_OWNER_PW }}
          repository: ${{ env.DOCKERHUB_REPOSITORY }}
          short-description: An API and Web client for managing STIG assessments.
          readme-filepath: ./docs/the-project/DockerHub_Readme.md


================================================
FILE: .github/workflows/unit-tests.yml
================================================
name: Unit tests
on:
  workflow_dispatch:
  pull_request:
    branches:
      - main
    paths:
      - "api/source/**"
      - "test/unit/**"
      - ".github/workflows/unit-tests.yml"
  push:
    branches:
      - main
    paths:
      - "api/source/**"
      - "test/unit/**"
      - ".github/workflows/unit-tests.yml"

jobs:
  unit-tests:
    name: Run unit tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - name: Install API dependencies
        run: npm ci
        working-directory: ./api/source/
      - name: Install test dependencies
        run: npm ci
        working-directory: ./test/unit/
      - name: Run unit tests
        working-directory: ./test/unit/
        run: npm test


================================================
FILE: .readthedocs.yml
================================================
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the OS, Python version and other tools you might need
build:
  os: ubuntu-22.04
  tools:
    python: "3.12"

    
# Build documentation in the docs/ directory with Sphinx
sphinx:
   configuration: docs/conf.py

# Optionally build your docs in additional formats such as PDF
# formats:
   # - pdf

# Optionally set the version of Python and requirements required to build your docs
python:
   install:
   - requirements: docs/requirements.txt

================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to STIG Manager

**NOTE: This CONTRIBUTING.md describes our software contribution policy. You do not need to follow the Developer's Certificate of Origin (DCO) process for commenting on the STIG Manager repository documentation, such as CONTRIBUTING.md, INTENT.md, etc. or for submitting issues. For more information about developing and contributing to the project, please see the [STIG Manager Contribution Guide](https://stig-manager.readthedocs.io/en/latest/the-project/contributing.html) that is part of our [overall documentation](https://stig-manager.readthedocs.io/en/latest/index.html)**

## Policy

### 1. Introduction

The project maintainer for this Project will only accept contributions using the Developer's Certificate of Origin 1.1 located at [developercertificate.org](https://developercertificate.org) ("DCO"). The DCO is a legally binding statement asserting that you are the creator of your contribution, or that you otherwise have the authority to distribute the contribution, and that you are intentionally making the contribution available under the license associated with the Project ("License").

### 2. Developer Certificate of Origin Process

Before submitting contributing code to this repository for the first time, you'll need to sign a Developer Certificate of Origin (DCO) (see below). To agree to the DCO, add your name and email address to the [CONTRIBUTORS.md](CONTRIBUTORS.md) file. At a high level, adding your information to this file tells us that you have the right to submit the work you're contributing and indicates that you consent to our treating the contribution in a way consistent with the license associated with this software (as described in [LICENSE.md](LICENSE.md)) and its documentation ("Project").

### 3. Important Points

Pseudonymous or anonymous contributions are permissible, but you must be reachable at the email address provided in the Signed-off-by line.

If your contribution is significant, you are also welcome to add your name and copyright date to the source file header.

U.S. Federal law prevents the government from accepting gratuitous services unless certain conditions are met. By submitting a pull request, you acknowledge that your services are offered without expectation of payment and that you expressly waive any future pay claims against the U.S. Federal government related to your contribution.

If you are a U.S. Federal government employee and use a `*.mil` or `*.gov` email address, we interpret your Signed-off-by to mean that the contribution was created in whole or in part by you and that your contribution is not subject to copyright protections.

### 4. DCO Text

The full text of the DCO is included below and is available online at [developercertificate.org](https://developercertificate.org):

```txt
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
```


================================================
FILE: CONTRIBUTORS.md
================================================
# Contributors

**By adding your name, email address, and copyright date below, you understand and agree to the terms of the [Developer's Certificate of Origin](https://developercertificate.org/) (DCO) version 1.1, and you are submitting all contributions you make to this Project pursuant to the terms described in [LICENSE.md](LICENSE.md).**

## Signed-off-by

- Copyright 2020-2026 U.S. Federal Government (in countries where recognized)
- Copyright 2020-2026 Carl Smigielski, carl.a.smigielski@saic.com
- Copyright 2020-2026 Christopher Daley, cdaley@rite-solutions.com
- Copyright 2023-2026 Mathew Ferreira, mferreira@rite-solutions.com
- Copyright 2021 Russell Johnson, russell.d.johnson@saic.com
- Copyright 2024 Rajesh Shrestha, rshrestha@rite-solutions.com
- Copyright 2024 David Whalen, david.whalen@usmc.mil
- Copyright 2025 Christian Rodriguez, christian.a.rodriguez@mantech.com
- _Add the copyright date, your name, and email address here. (PLEASE KEEP THIS LINE)_

## Note for U.S. Federal Employees

If you're a U.S. Federal Government employee and use a `*.mil` or `*.gov` email address to agree to the DCO, we interpret your signed DCO to mean that the contribution was created in whole or in part by you as part of your job with the U.S. Federal Government and that your contribution is not subject to copyright protections.


================================================
FILE: Dockerfile
================================================
# STIG Manager OSS
# 
# COPY commands assume the following lines in .dockerignore
# **/node_modules
# **/state.json
# **/README.md
# **/.git
# **/.gitignore
# **/data
# **/docs
# **/test
# **/uploads
# **/docker

ARG BASE_IMAGE="node:lts-alpine"
FROM ${BASE_IMAGE}
LABEL maintainer="carl.a.smigielski@saic.com"
ARG COMMIT_BRANCH=""
ARG COMMIT_SHA=""
ARG COMMIT_TAG=""
ARG COMMIT_DESCRIBE=""
LABEL commit-branch=${COMMIT_BRANCH}
LABEL commit-sha=${COMMIT_SHA}
LABEL commit-tag=${COMMIT_TAG}
LABEL commit-describe=${COMMIT_DESCRIBE}

WORKDIR /home/node
USER node

# Install app dependencies
COPY --chown=node:node ./api/source .
RUN npm ci

RUN mkdir client
# Requires the client build files. Alternatively, copy ./client/src 
COPY --chown=node:node ./client/dist ./client

RUN mkdir docs
COPY --chown=node:node ./docs/_build/html ./docs

# Ensure sticky bit is set on all world-writable directories (fixes tenable 1000749)
USER root
RUN df -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t 2>/dev/null | echo 'tenable 1000749'
USER node

# Set environment
ENV COMMIT_SHA=${COMMIT_SHA} \
COMMIT_BRANCH=${COMMIT_BRANCH} \
COMMIT_TAG=${COMMIT_TAG} \
COMMIT_DESCRIBE=${COMMIT_DESCRIBE} \
STIGMAN_CLIENT_DIRECTORY=./client \
STIGMAN_DOCS_DIRECTORY=./docs

EXPOSE 54000
CMD [ "node", "index.js" ]


================================================
FILE: INTENT.md
================================================
# Licensing Intent
The intent is that this software and documentation ("Project") should be treated as if it is licensed under the license associated with the Project ("License") in the LICENSE.md file. However, because we are part of the United States (U.S.) Federal Government, it is not that simple.

The portions of this Project written by United States (U.S.) Federal government employees within the scope of their federal employment are ineligible for copyright protection in the U.S.; this is generally understood to mean that these portions of the Project are placed in the public domain.

In countries where copyright protection is available (which does not include the U.S.), contributions made by U.S. Federal government employees are released under the License. Merged contributions from private contributors are released under the License.


================================================
FILE: LICENSE.md
================================================

---

*For all code except the STIG Manager client*

---

## MIT License

```
Copyright (c) 2020-2026 U.S. Federal Government (in countries where recognized)
Copyright (c) 2020-2026 Science Applications International Corporation
Copyright (c) 2020-2026 Rite-Solutions, An Arcfield Company

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
```
---

*For the STIG Manager client, which uses the ExtJS 3.4 JavaScript framework licensed under the GNU General Public License*

---

## GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

Copyright (C) 2007 [Free Software Foundation, Inc.](http://fsf.org/)

Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.

## Preamble

The GNU General Public License is a free, copyleft license for software and
other kinds of works.

The licenses for most software and other practical works are designed to take
away your freedom to share and change the works. By contrast, the GNU General
Public License is intended to guarantee your freedom to share and change all
versions of a program--to make sure it remains free software for all its users.
We, the Free Software Foundation, use the GNU General Public License for most
of our software; it applies also to any other work released this way by its
authors. You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom to
distribute copies of free software (and charge for them if you wish), that you
receive source code or can get it if you want it, that you can change the
software or use pieces of it in new free programs, and that you know you can do
these things.

To protect your rights, we need to prevent others from denying you these rights
or asking you to surrender the rights. Therefore, you have certain
responsibilities if you distribute copies of the software, or if you modify it:
responsibilities to respect the freedom of others.

For example, if you distribute copies of such a program, whether gratis or for
a fee, you must pass on to the recipients the same freedoms that you received.
You must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.

Developers that use the GNU GPL protect your rights with two steps:

  1. assert copyright on the software, and
  2. offer you this License giving you legal permission to copy, distribute
     and/or modify it.

For the developers' and authors' protection, the GPL clearly explains that
there is no warranty for this free software. For both users' and authors' sake,
the GPL requires that modified versions be marked as changed, so that their
problems will not be attributed erroneously to authors of previous versions.

Some devices are designed to deny users access to install or run modified
versions of the software inside them, although the manufacturer can do so. This
is fundamentally incompatible with the aim of protecting users' freedom to
change the software. The systematic pattern of such abuse occurs in the area of
products for individuals to use, which is precisely where it is most
unacceptable. Therefore, we have designed this version of the GPL to prohibit
the practice for those products. If such problems arise substantially in other
domains, we stand ready to extend this provision to those domains in future
versions of the GPL, as needed to protect the freedom of users.

Finally, every program is threatened constantly by software patents. States
should not allow patents to restrict development and use of software on
general-purpose computers, but in those that do, we wish to avoid the special
danger that patents applied to a free program could make it effectively
proprietary. To prevent this, the GPL assures that patents cannot be used to
render the program non-free.

The precise terms and conditions for copying, distribution and modification
follow.

## TERMS AND CONDITIONS

### 0. Definitions.

*This License* refers to version 3 of the GNU General Public License.

*Copyright* also means copyright-like laws that apply to other kinds of works,
such as semiconductor masks.

*The Program* refers to any copyrightable work licensed under this License.
Each licensee is addressed as *you*. *Licensees* and *recipients* may be
individuals or organizations.

To *modify* a work means to copy from or adapt all or part of the work in a
fashion requiring copyright permission, other than the making of an exact copy.
The resulting work is called a *modified version* of the earlier work or a work
*based on* the earlier work.

A *covered work* means either the unmodified Program or a work based on the
Program.

To *propagate* a work means to do anything with it that, without permission,
would make you directly or secondarily liable for infringement under applicable
copyright law, except executing it on a computer or modifying a private copy.
Propagation includes copying, distribution (with or without modification),
making available to the public, and in some countries other activities as well.

To *convey* a work means any kind of propagation that enables other parties to
make or receive copies. Mere interaction with a user through a computer
network, with no transfer of a copy, is not conveying.

An interactive user interface displays *Appropriate Legal Notices* to the
extent that it includes a convenient and prominently visible feature that

  1. displays an appropriate copyright notice, and
  2. tells the user that there is no warranty for the work (except to the
     extent that warranties are provided), that licensees may convey the work
     under this License, and how to view a copy of this License.

If the interface presents a list of user commands or options, such as a menu, a
prominent item in the list meets this criterion.

### 1. Source Code.

The *source code* for a work means the preferred form of the work for making
modifications to it. *Object code* means any non-source form of a work.

A *Standard Interface* means an interface that either is an official standard
defined by a recognized standards body, or, in the case of interfaces specified
for a particular programming language, one that is widely used among developers
working in that language.

The *System Libraries* of an executable work include anything, other than the
work as a whole, that (a) is included in the normal form of packaging a Major
Component, but which is not part of that Major Component, and (b) serves only
to enable use of the work with that Major Component, or to implement a Standard
Interface for which an implementation is available to the public in source code
form. A *Major Component*, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system (if any) on
which the executable work runs, or a compiler used to produce the work, or an
object code interpreter used to run it.

The *Corresponding Source* for a work in object code form means all the source
code needed to generate, install, and (for an executable work) run the object
code and to modify the work, including scripts to control those activities.
However, it does not include the work's System Libraries, or general-purpose
tools or generally available free programs which are used unmodified in
performing those activities but which are not part of the work. For example,
Corresponding Source includes interface definition files associated with source
files for the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require, such as
by intimate data communication or control flow between those subprograms and
other parts of the work.

The Corresponding Source need not include anything that users can regenerate
automatically from other parts of the Corresponding Source.

The Corresponding Source for a work in source code form is that same work.

### 2. Basic Permissions.

All rights granted under this License are granted for the term of copyright on
the Program, and are irrevocable provided the stated conditions are met. This
License explicitly affirms your unlimited permission to run the unmodified
Program. The output from running a covered work is covered by this License only
if the output, given its content, constitutes a covered work. This License
acknowledges your rights of fair use or other equivalent, as provided by
copyright law.

You may make, run and propagate covered works that you do not convey, without
conditions so long as your license otherwise remains in force. You may convey
covered works to others for the sole purpose of having them make modifications
exclusively for you, or provide you with facilities for running those works,
provided that you comply with the terms of this License in conveying all
material for which you do not control copyright. Those thus making or running
the covered works for you must do so exclusively on your behalf, under your
direction and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

Conveying under any other circumstances is permitted solely under the
conditions stated below. Sublicensing is not allowed; section 10 makes it
unnecessary.

### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.

No covered work shall be deemed part of an effective technological measure
under any applicable law fulfilling obligations under article 11 of the WIPO
copyright treaty adopted on 20 December 1996, or similar laws prohibiting or
restricting circumvention of such measures.

When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention is
effected by exercising rights under this License with respect to the covered
work, and you disclaim any intention to limit operation or modification of the
work as a means of enforcing, against the work's users, your or third parties'
legal rights to forbid circumvention of technological measures.

### 4. Conveying Verbatim Copies.

You may convey verbatim copies of the Program's source code as you receive it,
in any medium, provided that you conspicuously and appropriately publish on
each copy an appropriate copyright notice; keep intact all notices stating that
this License and any non-permissive terms added in accord with section 7 apply
to the code; keep intact all notices of the absence of any warranty; and give
all recipients a copy of this License along with the Program.

You may charge any price or no price for each copy that you convey, and you may
offer support or warranty protection for a fee.

### 5. Conveying Modified Source Versions.

You may convey a work based on the Program, or the modifications to produce it
from the Program, in the form of source code under the terms of section 4,
provided that you also meet all of these conditions:

  - a) The work must carry prominent notices stating that you modified it, and
    giving a relevant date.
  - b) The work must carry prominent notices stating that it is released under
    this License and any conditions added under section 7. This requirement
    modifies the requirement in section 4 to *keep intact all notices*.
  - c) You must license the entire work, as a whole, under this License to
    anyone who comes into possession of a copy. This License will therefore
    apply, along with any applicable section 7 additional terms, to the whole
    of the work, and all its parts, regardless of how they are packaged. This
    License gives no permission to license the work in any other way, but it
    does not invalidate such permission if you have separately received it.
  - d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your work need
    not make them do so.

A compilation of a covered work with other separate and independent works,
which are not by their nature extensions of the covered work, and which are not
combined with it such as to form a larger program, in or on a volume of a
storage or distribution medium, is called an *aggregate* if the compilation and
its resulting copyright are not used to limit the access or legal rights of the
compilation's users beyond what the individual works permit. Inclusion of a
covered work in an aggregate does not cause this License to apply to the other
parts of the aggregate.

### 6. Conveying Non-Source Forms.

You may convey a covered work in object code form under the terms of sections 4
and 5, provided that you also convey the machine-readable Corresponding Source
under the terms of this License, in one of these ways:

  - a) Convey the object code in, or embodied in, a physical product (including
    a physical distribution medium), accompanied by the Corresponding Source
    fixed on a durable physical medium customarily used for software
    interchange.
  - b) Convey the object code in, or embodied in, a physical product (including
    a physical distribution medium), accompanied by a written offer, valid for
    at least three years and valid for as long as you offer spare parts or
    customer support for that product model, to give anyone who possesses the
    object code either
    1. a copy of the Corresponding Source for all the software in the product
       that is covered by this License, on a durable physical medium
       customarily used for software interchange, for a price no more than your
       reasonable cost of physically performing this conveying of source, or
    2. access to copy the Corresponding Source from a network server at no
       charge.
  - c) Convey individual copies of the object code with a copy of the written
    offer to provide the Corresponding Source. This alternative is allowed only
    occasionally and noncommercially, and only if you received the object code
    with such an offer, in accord with subsection 6b.
  - d) Convey the object code by offering access from a designated place
    (gratis or for a charge), and offer equivalent access to the Corresponding
    Source in the same way through the same place at no further charge. You
    need not require recipients to copy the Corresponding Source along with the
    object code. If the place to copy the object code is a network server, the
    Corresponding Source may be on a different server operated by you or a
    third party) that supports equivalent copying facilities, provided you
    maintain clear directions next to the object code saying where to find the
    Corresponding Source. Regardless of what server hosts the Corresponding
    Source, you remain obligated to ensure that it is available for as long as
    needed to satisfy these requirements.
  - e) Convey the object code using peer-to-peer transmission, provided you
    inform other peers where the object code and Corresponding Source of the
    work are being offered to the general public at no charge under subsection
    6d.

A separable portion of the object code, whose source code is excluded from the
Corresponding Source as a System Library, need not be included in conveying the
object code work.

A *User Product* is either

  1. a *consumer product*, which means any tangible personal property which is
     normally used for personal, family, or household purposes, or
  2. anything designed or sold for incorporation into a dwelling.

In determining whether a product is a consumer product, doubtful cases shall be
resolved in favor of coverage. For a particular product received by a
particular user, *normally used* refers to a typical or common use of that
class of product, regardless of the status of the particular user or of the way
in which the particular user actually uses, or expects or is expected to use,
the product. A product is a consumer product regardless of whether the product
has substantial commercial, industrial or non-consumer uses, unless such uses
represent the only significant mode of use of the product.

*Installation Information* for a User Product means any methods, procedures,
authorization keys, or other information required to install and execute
modified versions of a covered work in that User Product from a modified
version of its Corresponding Source. The information must suffice to ensure
that the continued functioning of the modified object code is in no case
prevented or interfered with solely because modification has been made.

If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as part of a
transaction in which the right of possession and use of the User Product is
transferred to the recipient in perpetuity or for a fixed term (regardless of
how the transaction is characterized), the Corresponding Source conveyed under
this section must be accompanied by the Installation Information. But this
requirement does not apply if neither you nor any third party retains the
ability to install modified object code on the User Product (for example, the
work has been installed in ROM).

The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates for a
work that has been modified or installed by the recipient, or for the User
Product in which it has been modified or installed. Access to a network may be
denied when the modification itself materially and adversely affects the
operation of the network or violates the rules and protocols for communication
across the network.

Corresponding Source conveyed, and Installation Information provided, in accord
with this section must be in a format that is publicly documented (and with an
implementation available to the public in source code form), and must require
no special password or key for unpacking, reading or copying.

### 7. Additional Terms.

*Additional permissions* are terms that supplement the terms of this License by
making exceptions from one or more of its conditions. Additional permissions
that are applicable to the entire Program shall be treated as though they were
included in this License, to the extent that they are valid under applicable
law. If additional permissions apply only to part of the Program, that part may
be used separately under those permissions, but the entire Program remains
governed by this License without regard to the additional permissions.

When you convey a copy of a covered work, you may at your option remove any
additional permissions from that copy, or from any part of it. (Additional
permissions may be written to require their own removal in certain cases when
you modify the work.) You may place additional permissions on material, added
by you to a covered work, for which you have or can give appropriate copyright
permission.

Notwithstanding any other provision of this License, for material you add to a
covered work, you may (if authorized by the copyright holders of that material)
supplement the terms of this License with terms:

  - a) Disclaiming warranty or limiting liability differently from the terms of
    sections 15 and 16 of this License; or
  - b) Requiring preservation of specified reasonable legal notices or author
    attributions in that material or in the Appropriate Legal Notices displayed
    by works containing it; or
  - c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in reasonable
    ways as different from the original version; or
  - d) Limiting the use for publicity purposes of names of licensors or authors
    of the material; or
  - e) Declining to grant rights under trademark law for use of some trade
    names, trademarks, or service marks; or
  - f) Requiring indemnification of licensors and authors of that material by
    anyone who conveys the material (or modified versions of it) with
    contractual assumptions of liability to the recipient, for any liability
    that these contractual assumptions directly impose on those licensors and
    authors.

All other non-permissive additional terms are considered *further restrictions*
within the meaning of section 10. If the Program as you received it, or any
part of it, contains a notice stating that it is governed by this License along
with a term that is a further restriction, you may remove that term. If a
license document contains a further restriction but permits relicensing or
conveying under this License, you may add to a covered work material governed
by the terms of that license document, provided that the further restriction
does not survive such relicensing or conveying.

If you add terms to a covered work in accord with this section, you must place,
in the relevant source files, a statement of the additional terms that apply to
those files, or a notice indicating where to find the applicable terms.

Additional terms, permissive or non-permissive, may be stated in the form of a
separately written license, or stated as exceptions; the above requirements
apply either way.

### 8. Termination.

You may not propagate or modify a covered work except as expressly provided
under this License. Any attempt otherwise to propagate or modify it is void,
and will automatically terminate your rights under this License (including any
patent licenses granted under the third paragraph of section 11).

However, if you cease all violation of this License, then your license from a
particular copyright holder is reinstated

  - a) provisionally, unless and until the copyright holder explicitly and
    finally terminates your license, and
  - b) permanently, if the copyright holder fails to notify you of the
    violation by some reasonable means prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is reinstated
permanently if the copyright holder notifies you of the violation by some
reasonable means, this is the first time you have received notice of violation
of this License (for any work) from that copyright holder, and you cure the
violation prior to 30 days after your receipt of the notice.

Termination of your rights under this section does not terminate the licenses
of parties who have received copies or rights from you under this License. If
your rights have been terminated and not permanently reinstated, you do not
qualify to receive new licenses for the same material under section 10.

### 9. Acceptance Not Required for Having Copies.

You are not required to accept this License in order to receive or run a copy
of the Program. Ancillary propagation of a covered work occurring solely as a
consequence of using peer-to-peer transmission to receive a copy likewise does
not require acceptance. However, nothing other than this License grants you
permission to propagate or modify any covered work. These actions infringe
copyright if you do not accept this License. Therefore, by modifying or
propagating a covered work, you indicate your acceptance of this License to do
so.

### 10. Automatic Licensing of Downstream Recipients.

Each time you convey a covered work, the recipient automatically receives a
license from the original licensors, to run, modify and propagate that work,
subject to this License. You are not responsible for enforcing compliance by
third parties with this License.

An *entity transaction* is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered work
results from an entity transaction, each party to that transaction who receives
a copy of the work also receives whatever licenses to the work the party's
predecessor in interest had or could give under the previous paragraph, plus a
right to possession of the Corresponding Source of the work from the
predecessor in interest, if the predecessor has it or can get it with
reasonable efforts.

You may not impose any further restrictions on the exercise of the rights
granted or affirmed under this License. For example, you may not impose a
license fee, royalty, or other charge for exercise of rights granted under this
License, and you may not initiate litigation (including a cross-claim or
counterclaim in a lawsuit) alleging that any patent claim is infringed by
making, using, selling, offering for sale, or importing the Program or any
portion of it.

### 11. Patents.

A *contributor* is a copyright holder who authorizes use under this License of
the Program or a work on which the Program is based. The work thus licensed is
called the contributor's *contributor version*.

A contributor's *essential patent claims* are all patent claims owned or
controlled by the contributor, whether already acquired or hereafter acquired,
that would be infringed by some manner, permitted by this License, of making,
using, or selling its contributor version, but do not include claims that would
be infringed only as a consequence of further modification of the contributor
version. For purposes of this definition, *control* includes the right to grant
patent sublicenses in a manner consistent with the requirements of this
License.

Each contributor grants you a non-exclusive, worldwide, royalty-free patent
license under the contributor's essential patent claims, to make, use, sell,
offer for sale, import and otherwise run, modify and propagate the contents of
its contributor version.

In the following three paragraphs, a *patent license* is any express agreement
or commitment, however denominated, not to enforce a patent (such as an express
permission to practice a patent or covenant not to sue for patent
infringement). To *grant* such a patent license to a party means to make such
an agreement or commitment not to enforce a patent against the party.

If you convey a covered work, knowingly relying on a patent license, and the
Corresponding Source of the work is not available for anyone to copy, free of
charge and under the terms of this License, through a publicly available
network server or other readily accessible means, then you must either

  1. cause the Corresponding Source to be so available, or
  2. arrange to deprive yourself of the benefit of the patent license for this
     particular work, or
  3. arrange, in a manner consistent with the requirements of this License, to
     extend the patent license to downstream recipients.

*Knowingly relying* means you have actual knowledge that, but for the patent
license, your conveying the covered work in a country, or your recipient's use
of the covered work in a country, would infringe one or more identifiable
patents in that country that you have reason to believe are valid.

If, pursuant to or in connection with a single transaction or arrangement, you
convey, or propagate by procuring conveyance of, a covered work, and grant a
patent license to some of the parties receiving the covered work authorizing
them to use, propagate, modify or convey a specific copy of the covered work,
then the patent license you grant is automatically extended to all recipients
of the covered work and works based on it.

A patent license is *discriminatory* if it does not include within the scope of
its coverage, prohibits the exercise of, or is conditioned on the non-exercise
of one or more of the rights that are specifically granted under this License.
You may not convey a covered work if you are a party to an arrangement with a
third party that is in the business of distributing software, under which you
make payment to the third party based on the extent of your activity of
conveying the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory patent
license

  - a) in connection with copies of the covered work conveyed by you (or copies
    made from those copies), or
  - b) primarily for and in connection with specific products or compilations
    that contain the covered work, unless you entered into that arrangement, or
    that patent license was granted, prior to 28 March 2007.

Nothing in this License shall be construed as excluding or limiting any implied
license or other defenses to infringement that may otherwise be available to
you under applicable patent law.

### 12. No Surrender of Others' Freedom.

If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not excuse
you from the conditions of this License. If you cannot convey a covered work so
as to satisfy simultaneously your obligations under this License and any other
pertinent obligations, then as a consequence you may not convey it at all. For
example, if you agree to terms that obligate you to collect a royalty for
further conveying from those to whom you convey the Program, the only way you
could satisfy both those terms and this License would be to refrain entirely
from conveying the Program.

### 13. Use with the GNU Affero General Public License.

Notwithstanding any other provision of this License, you have permission to
link or combine any covered work with a work licensed under version 3 of the
GNU Affero General Public License into a single combined work, and to convey
the resulting work. The terms of this License will continue to apply to the
part which is the covered work, but the special requirements of the GNU Affero
General Public License, section 13, concerning interaction through a network
will apply to the combination as such.

### 14. Revised Versions of this License.

The Free Software Foundation may publish revised and/or new versions of the GNU
General Public License from time to time. Such new versions will be similar in
spirit to the present version, but may differ in detail to address new problems
or concerns.

Each version is given a distinguishing version number. If the Program specifies
that a certain numbered version of the GNU General Public License *or any later
version* applies to it, you have the option of following the terms and
conditions either of that numbered version or of any later version published by
the Free Software Foundation. If the Program does not specify a version number
of the GNU General Public License, you may choose any version ever published by
the Free Software Foundation.

If the Program specifies that a proxy can decide which future versions of the
GNU General Public License can be used, that proxy's public statement of
acceptance of a version permanently authorizes you to choose that version for
the Program.

Later license versions may give you additional or different permissions.
However, no additional obligations are imposed on any author or copyright
holder as a result of your choosing to follow a later version.

### 15. Disclaimer of Warranty.

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
PARTIES PROVIDE THE PROGRAM *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.

### 16. Limitation of Liability.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

### 17. Interpretation of Sections 15 and 16.

If the disclaimer of warranty and limitation of liability provided above cannot
be given local legal effect according to their terms, reviewing courts shall
apply local law that most closely approximates an absolute waiver of all civil
liability in connection with the Program, unless a warranty or assumption of
liability accompanies a copy of the Program in return for a fee.

## END OF TERMS AND CONDITIONS ###

### How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible
use to the public, the best way to achieve this is to make it free software
which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach
them to the start of each source file to most effectively state the exclusion
of warranty; and each file should have at least the *copyright* line and a
pointer to where the full notice is found.

	<one line to give the program's name and a brief idea of what it does.>
	Copyright (C) <year>  <name of author>
	
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

If the program does terminal interaction, make it output a short notice like
this when it starts in an interactive mode:

	<program>  Copyright (C) <year>  <name of author>
	This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
	This is free software, and you are welcome to redistribute it
	under certain conditions; type `show c' for details.

The hypothetical commands `show w` and `show c` should show the appropriate
parts of the General Public License. Of course, your program's commands might
be different; for a GUI interface, you would use an *about box*.

You should also get your employer (if you work as a programmer) or school, if
any, to sign a *copyright disclaimer* for the program, if necessary. For more
information on this, and how to apply and follow the GNU GPL, see
[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).

The GNU General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may consider
it more useful to permit linking proprietary applications with the library. If
this is what you want to do, use the GNU Lesser General Public License instead
of this License. But first, please read
[http://www.gnu.org/philosophy/why-not-lgpl.html](http://www.gnu.org/philosophy/why-not-lgpl.html).

---

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.




================================================
FILE: README.md
================================================
# STIG Manager

STIG Manager is an API and web client for managing STIG assessments of Information Systems, sponsored by the [NAVSEA Warfare Centers](https://www.navsea.navy.mil/Home/Warfare-Centers/). The application presents a unified view of STIG compliance drawn from manual reviews in the web app, file imports (.ckl/.cklb/XCCDF), or automated integrations via the API. STIG Manager supports DISA [Security Technical Implementation Guides (STIGs)](https://public.cyber.mil/stigs/) and Security Requirements Guides (SRGs).

## Who It's For

If you need to track STIG evaluation status across multiple assets, STIGs, or systems, this tool addresses the challenges of managing assessment data that would otherwise be scattered across individual checklist files or spreadsheets.

System administrators can record compliance status in real-time as they harden systems, and scan results from external tools can flow in automatically via the API, providing ISSOs and security managers with live visibility into assessment progress. Working from a shared data set ensures all users maintain a consistent view of compliance status.

## Key Capabilities

- **Collection-Based Organization**: Group Assets, STIGs, and Reviews into Collections that align with your RMF packages or organizational structure; use customizable Labels to categorize Assets and filter views.
- **Progress Tracking and Metrics**: Real-time dashboards showing assessment completion rates, findings by severity, CORA risk scoring, and status tracking.
- **Multi-Source Review Integration**: Combine manual evaluations with imported scan results (XCCDF) and checklists (CKL) in a unified data management interface.
- **Intelligent STIG Revision Management**: When DISA releases new STIG versions, only Rules with changed check content require re-evaluation. Existing reviews are automatically matched to updated Rules where appropriate.
- **Bulk Operations**: Evaluate the same Rule across multiple Assets simultaneously in the Collection Review workspace, apply batch updates, and import/export entire Collections.
- **Collaborative Workflows**: Role-based access controls, Accept/Reject review validation, and configurable review requirements per Collection.
- **API-First Architecture**: Complete REST API (OpenAPI 3.0.1) enables integration with automated scanning tools and custom workflows. The API-first architecture allows custom or third-party clients to interact with assessment data. 

## Screenshots

### Collection Dashboard
*Real-time metrics showing assessment completion, findings by severity, and CORA risk scoring*

<img src="docs/assets/images/metrics-report-collection.png" alt="Collection Dashboard" width="800">

### Asset Review Workspace
*Assessment interface with Rule details, CCI/Control mappings, and reference to previous assessments on similar Assets*

<img src="docs/assets/images/asset-review.png" alt="Asset Review Workspace" width="800">

### Collection Review Workspace
*Evaluate the same STIG Rule across all Assets in a Collection, with color-coded status and the ability to apply bulk updates*

<img src="docs/assets/images/collection-review.png" alt="Collection Review Workspace" width="800">

### Meta-Collection Dashboard
*Aggregate metrics across all Collections you have access to, providing organization-wide visibility into assessment status*

<img src="docs/assets/images/meta-collection-dashboard.png" alt="Meta-Collection Dashboard" width="800">


## Role in RMF Workflows

STIG Manager primarily supports **RMF Steps 3 (Implement Security Controls)** and **4 (Assess Security Controls)** by serving as the authoritative reference for current STIG assessment status. During **Step 6 (Monitor Security Controls)**, it tracks review ages, maintains assessment history, and identifies what requires re-evaluation when STIGs update or systems change.

The tool fits within existing processes that typically involve eMASS (or similar RMF platforms), SCAP compliance scanners, and other security tools. STIG Manager does not replace these systems—it specializes in STIG assessment tracking and can import results from scanning tools, export checklists for package submission, and support custom automation via its API.

## Getting Started

- [User Walkthrough](https://stig-manager.readthedocs.io/en/latest/user-guide/user-quickstart.html) - Learn the core workflows for security analysts
- [Admin Walkthrough](https://stig-manager.readthedocs.io/en/latest/admin-guide/admin-quickstart.html) - Setup and Collection management for Application Managers
- [Installation Guide](https://stig-manager.readthedocs.io/en/latest/installation-and-setup/installation-and-setup.html) - Deployment instructions and configuration
- [Environment Variables Reference](https://stig-manager.readthedocs.io/en/latest/installation-and-setup/environment-variables.html)

## Deployment Options

**Containerized (Recommended):**
- Official [Docker images](https://hub.docker.com/r/nuwcdivnpt/stig-manager) available on Docker Hub and DoD Iron Bank
  - Quick-start Docker Compose orchestration includes all dependencies (Keycloak, MySQL)
- [Reference orchestration with CAC/PKI authentication](https://github.com/NUWCDIVNPT/stigman-orchestration) demonstrates nginx reverse proxy integration
  - Supports Kubernetes, OpenShift, or any OCI-compliant container runtime

**Direct Deployment:**
- Run from source using Node.js LTS
- Pre-compiled binaries for Windows/Linux/macOS (no Node.js required)

**Infrastructure Requirements:**
- OpenID Connect (OIDC) provider for authentication (Keycloak, Okta, Azure Entra ID, and F5 tested)
- MySQL 8.4+ database
- Optional reverse proxy for CAC/PKI authentication

The application is stateless and can scale horizontally. Configuration is managed entirely through environment variables.

## Documentation and Resources

The [STIG Manager documentation](https://stig-manager.readthedocs.io/en/latest/index.html) includes User and Setup Guides, video tutorials, terminology references, and deployment scenarios.

- [YouTube Channel](https://www.youtube.com/@stig-manager) - Video tutorials and feature demonstrations
- [Release Notes](https://github.com/NUWCDIVNPT/stig-manager/releases) - Version history
- [Contribution Guide](CONTRIBUTING.md) - DCO requirements and development setup

## Related Resources

**[STIGMan Watcher](https://github.com/NUWCDIVNPT/stigman-watcher)** - A command-line utility that monitors filesystem directories and automatically imports .ckl/.cklb checklists and XCCDF scan results into STIG Manager. Useful for automated workflows and continuous integration with scanning tools.

**[Reference orchestration with CAC/PKI authentication](https://github.com/NUWCDIVNPT/stigman-orchestration)** - A sample Docker Compose setup that includes nginx configured for CAC/PKI authentication in front of STIG Manager and Keycloak.

**[C-PAT](https://github.com/NSWC-Crane/C-PAT)** - The Crane POA&M Automation Tool, developed by NSWC Crane, integrates with STIG Manager's API to automate vulnerability documentation and POA&M tracking throughout the RMF process.


## Sponsor

STIG Manager is sponsored by the [NAVSEA Warfare Centers](https://www.navsea.navy.mil/Home/Warfare-Centers/). While its primary goal is to support NAVSEA compliance processes, the tool is designed to be flexible and adaptable to other workflows. This project follows [Code.mil](https://code.mil) [guidance](https://github.com/Code-dot-mil/code.mil) for open source software released by the U.S. Department of Defense.

For inquiries, contact the RMF Tools team at RMF_Tools@us.navy.mil.

================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

The STIG Manager Team makes every effort to produce secure software. The project addresses vulnerabilities in the application with new mainline releases. Old versions will not be patched. All users are expected to stay up to date with security and feature updates by running only the latest release available. 

| Version | Supported          |
| ------- | ------------------ |
| Current   | :white_check_mark: |
| All previous   | :x:                |


## Reporting a Vulnerability

Vulnerability scans are run regularly against project components and any issues identified are addressed. Nevertheless, we are grateful to anyone reporting a vulnerability and helping us to make STIG Manager better and more secure. Additionally, we encourage everyone to disclose bugs in a responsible way, allowing us and other STIGMan users to react accordingly and in a timely manner. That means:

- If you want to report a critical security bug or vulnerability please send a bug report to RMF_Tools@us.navy.mil before publishing it. We will acknowledge your email within a week (7 days), and will send a more detailed response up to 48 hours after that indicating the next steps in handling your report. After the initial reply to your report, the security team will endeavor to keep you informed of the progress towards a fix and an announcement. We may ask for additional information or guidance. When disclosing vulnerabilities please include the following:
    - The word "SECURITY" in the subject line.
    - Your name and affiliation (if any).
    - Scope of vulnerability. Let us know who could use this exploit.
    - Documented steps to identify the vulnerability. It is important that we can reproduce your findings.


- If you want to report a non-critical bug, please open an issue on the GitHub project. If you are using a scanning tool to identify a vulnerability, please attempt to determine whether or not the issue is a false positive before reporting, and if it is not, include the specific scanner, settings, and config you used to identify it.

- Report security bugs in third-party modules to the person or team maintaining the module.

- This is an open source project. If you discover a bug and fix it, you are very welcome to submit a PR. Your fix will be reviewed, and if accepted, you will become a valued addition to our CONTRIBUTORS.md file!

- Known vulnerabilities will be published on the [Security Advisories page of the project's GitHub site.](https://github.com/NUWCDIVNPT/stig-manager/security/advisories)


## Securing STIG Manager

STIG Manager is one component of a system that must be deployed according to your individual or organizational security requirements. 

Please see the [project Documentation for more information on this topic.](https://stig-manager.readthedocs.io/en/latest/installation-and-setup/securing.html)


================================================
FILE: api/README.md
================================================
# STIG Manager API for Node.js

## Required Node version
The API requires Node 14.0.0 or greater

## Building binaries
- Read the comments in `build.sh` regarding build requirements
- Run `./build.sh` or `build.sh --sign`
- Binaries are written to `./bin`
- Archives with launcher scripts are written to `./dist`

## Configuring and running the API
The API is configured through [environment variables](../docs/Environment_Variables.md). The entry point is `index.js`


================================================
FILE: api/bin/.gitignore
================================================
## Directory for the STIG Manager API binaries

# Content can be written here by executing:
# $ ../build.sh
#
# This file hopes to prevent commits to this directory

# Ignore everything in this directory
*

# Except this file
!.gitignore


================================================
FILE: api/build.sh
================================================
#!/bin/bash

# This file is used to build API binaries on the team workstations. It is not tested elsewhere, yet.
# Requires:
# - Node.js and module "@yao-pkg/pkg" (npm install -g @yao-pkg/pkg@6.10)
# - zip
# - tar


check_exit_status() {
  if [[ $? -eq 0 ]]; then
    echo "[BUILD_TASK] $1 succeeded"
  else
    echo "[BUILD_TASK] $1 failed"
    exit $2
  fi
}

LAUNCHERDIR=launchers
BINDIR=bin
DISTDIR=dist

# Change to this script directory
cd "$(dirname "$(realpath "$0")")"

# Prepare
[ ! -d "$BINDIR" ] && mkdir -p "$BINDIR"
[ ! -d "$DISTDIR" ] && mkdir -p "$DISTDIR"
rm -rf $BINDIR/*
rm -rf $DISTDIR/*
echo "Fetching node_modules"
rm -rf ./source/node_modules
cd ./source
npm ci
npm install -g @yao-pkg/pkg@6.10
cd ..
../client/build.sh
../docs/build.sh

DESCRIBE=$(git describe --tags | sed 's/\(.*\)-.*/\1/')
check_exit_status "Getting latest tag" 4
echo $DESCRIBE

# Make binaries
echo "Building binaries"
pkg ./source/index.js -C gzip --public --public-packages=* --no-bytecode -c pkg.config.json
check_exit_status "Building binaries" 1

echo "Creating archives with launchers"
# Windows archive
zip --junk-paths $DISTDIR/stig-manager-win-$DESCRIBE.zip $LAUNCHERDIR/stig-manager.bat $BINDIR/stig-manager-win.exe
check_exit_status "Zipping Windows Archive" 3

# Linux archive
tar -cJvf $DISTDIR/stig-manager-linux-$DESCRIBE.tar.xz --xform='s|^|stig-manager/|S' -C $LAUNCHERDIR stig-manager.sh -C ../$BINDIR stig-manager-linuxstatic
check_exit_status "Zipping Linux Archive" 4

echo "Build artifacts are in $DISTDIR"

================================================
FILE: api/dist/.gitignore
================================================
## Directory for the STIG Manager API distribution archives

# Content can be written here by executing:
# $ ../build.sh
#
# This file hopes to prevent commits to this directory

# Ignore everything in this directory
*

# Except this file
!.gitignore


================================================
FILE: api/launchers/gen-launchers.py
================================================
#!/usr/bin/python3
import sys
import os
import io
import csv
import textwrap

if len(sys.argv) > 1 and sys.argv[1] == 'win':
  system = 'win'
  comment = '::'
  command = 'set'
  launch = 'stig-manager-win.exe'
  filename = 'stig-manager.bat'
  newline = '\r\n'
else:
  system = 'linux'
  comment = '#'
  command = 'export'
  launch = './stig-manager-linuxstatic'
  filename = 'stig-manager.sh'
  newline = '\n'


with open('../../docs/installation-and-setup/envvars.csv', 'r') as csvfile:
    reader = csv.DictReader(csvfile)
    with io.open(filename, 'w', newline=newline) as f:
      for row in reader:
          row['Description'] = row['Description'].replace('**Default**', 'Default:')
          row['Description'] = row['Description'].replace('**No default**', 'No default.')
          row['Description'] = row['Description'].replace('``', '"')
          row['Description'] = '\n'.join(textwrap.wrap(row['Description'], width=80, initial_indent=comment + '  ', subsequent_indent=comment + '  '))
          f.write('{0}==============================================================================\n'.format(comment))
          content = '{0} {1}\n{0}\n{2}\n{0}\n{0}  Affects: {3}\n'.format(comment, row['Variable'], row['Description'], row['Affects'])
          f.write(content)
          f.write('{0}==============================================================================\n'.format(comment))
          f.write('{0} {1} {2}=\n'.format(comment, command, row['Variable']))
          f.write('\n')
      f.write(launch + '\n')

if system == 'linux':
  os.chmod(filename, 0o755)


================================================
FILE: api/launchers/stig-manager.bat
================================================
::==============================================================================
:: STIGMAN_API_ADDRESS
::
::  | Default: "0.0.0.0" | The IP address on which the the API server will
::  listen
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_ADDRESS=

::==============================================================================
:: STIGMAN_API_MAX_JSON_BODY
::
::  | Default: "5242880" | The maximum size in bytes of the request body when
::  Content-Type is application/json
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_MAX_JSON_BODY=

::==============================================================================
:: STIGMAN_API_MAX_UPLOAD
::
::  | Default: "1073741824" | The maximum size in bytes of the file uploaded
::  with Content-Type multipart/form-data
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_MAX_UPLOAD=

::==============================================================================
:: STIGMAN_API_PORT
::
::  | Default: "54000" | The TCP port on which the server will listen
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_PORT=

::==============================================================================
:: STIGMAN_API_TLS_CERT_FILE
::
::  | No default. | A absolute path to the file that contains the PEM encoded
::  Server certificate used for TLS. Additionally requires setting
::  "STIGMAN_API_TLS_KEY_FILE" to enable TLS.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_TLS_CERT_FILE=

::==============================================================================
:: STIGMAN_API_TLS_KEY_FILE
::
::  | No default. | A absolute path to the file that contains the PEM encoded
::  Server private key used for TLS. Additionally requires setting
::  "STIGMAN_API_TLS_CERT_FILE" to enable TLS.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_TLS_KEY_FILE=

::==============================================================================
:: STIGMAN_API_TLS_KEY_PASSPHRASE
::
::  | No default. | If necessary, the passphrase that decrypts the PEM encoded
::  Server private key used for TLS. Additionally requires setting
::  "STIGMAN_API_TLS_CERT_FILE" to enable TLS.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_API_TLS_KEY_PASSPHRASE=

::==============================================================================
:: STIGMAN_CLASSIFICATION
::
::  | Default: "U" | Sets the classification banner, if any. Available values:
::  "NONE" "U" "CUI" "C" "S" "TS" "SCI"
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_CLASSIFICATION=

::==============================================================================
:: STIGMAN_CLIENT_ADMIN_TIMEOUT
::
::  | Default: "0" | The maximum time (in minutes) a user with admin privileges
::  can be inactive in the web client before discarding their access token and
::  requiring reauthorization. Activity is defined as mouse click, keypress, or
::  scrolling in any tab or window of a same-origin browsing context group. Set
::  to zero to disable idle detection.
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_ADMIN_TIMEOUT=

::==============================================================================
:: STIGMAN_CLIENT_API_BASE
::
::  | Default: "api" | The base URL for Client requests to the API relative to
::  "window.location"
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_API_BASE=

::==============================================================================
:: STIGMAN_CLIENT_CONSOLE_MODE
::
::  | Default: "production" | The console mode of the web client, setting to
::  "development" enables console logging which is otherwise disabled
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_CONSOLE_MODE=

::==============================================================================
:: STIGMAN_CLIENT_DIRECTORY
::
::  | Default: "./clients" | The location of the web client files, relative to
::  the API source directory. Note that if running source from a clone of the
::  GitHub repository, the client is located at `../../clients` relative to the
::  API directory.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_CLIENT_DIRECTORY=

::==============================================================================
:: STIGMAN_CLIENT_DISABLED
::
::  | Default: "false" | Whether to *not* serve the reference web client
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_DISABLED=

::==============================================================================
:: STIGMAN_CLIENT_DISPLAY_APPMANAGERS
::
::  | Default: "true" | Whether to display application managers the home page of
::  web client
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_DISPLAY_APPMANAGERS=

::==============================================================================
:: STIGMAN_CLIENT_EXTRA_SCOPES
::
::  | No default. | A space separated list of OAuth2 scopes to request in
::  addition to "stig-manager:stig" "stig-manager:stig:read" "stig-
::  manager:collection" "stig-manager:user" "stig-manager:user:read" "stig-
::  manager:op". Some OIDC providers (Okta) generate a refresh token only if the
::  scope "offline_access" is requested
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_EXTRA_SCOPES=

::==============================================================================
:: STIGMAN_CLIENT_ID
::
::  | Default: "stig-manager" | The OIDC clientId of the web client
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_ID=

::==============================================================================
:: STIGMAN_CLIENT_OIDC_PROVIDER
::
::  | Default: Value of "STIGMAN_OIDC_PROVIDER" | Client override of the base
::  URL of the OIDC provider issuing signed JWTs for the API.  The string
::  "/.well-known/openid-configuration" will be appended by the client when
::  fetching metadata.
::
::  Affects: Client 
::==============================================================================
:: set STIGMAN_CLIENT_OIDC_PROVIDER=

::==============================================================================
:: STIGMAN_CLIENT_REAUTH_ACTION
::
::  | Default: "popup" | How to prompt for re-authentication when user
::  credentials expire. Available values: "popup", "iframe", "tab", or "reload".
::  See :ref:`stigman_client_reauth_action` in the Authentication document for
::  details.
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_REAUTH_ACTION=

::==============================================================================
:: STIGMAN_CLIENT_RESPONSE_MODE
::
::  | Default: "fragment" | The response_mode the web client should specify when
::  requesting an authorization code from the OIDC provider. Available values:
::  "fragment", "query"
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_RESPONSE_MODE=

::==============================================================================
:: STIGMAN_CLIENT_SCOPE_PREFIX
::
::  | No default. | String used as a prefix for each scope when authenticating
::  to the OIDC Provider. Some providers (Azure AD) expect scope requests in the
::  format "api://<application_id>/<scope>", where "api://<application_id>/" is
::  the required prefix.
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_SCOPE_PREFIX=

::==============================================================================
:: STIGMAN_CLIENT_STATE_EVENTS
::
::  | Default: "true" | Whether the web client listens for server sent events
::  (SSE) about the API state. Should only be disabled temporarily while
::  resolving buffering issues on a reverse proxy.
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_STATE_EVENTS=

::==============================================================================
:: STIGMAN_CLIENT_STRICT_PKCE
::
::  | Default: "true" | Whether the web client verifies the OIDC provider is
::  advertising PKCE/S256 support in compliance with RFC 8414. A non-compliant
::  provider supports PKCE/S256 without advertising it. Independent of this
::  value, the web client always exclusively uses PKCE/S256 in the Authorization
::  Code Flow.
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_STRICT_PKCE=

::==============================================================================
:: STIGMAN_CLIENT_USER_TIMEOUT
::
::  | Default: "0" | The maximum time (in minutes) a regular user can be
::  inactive in the web client before discarding their access token and
::  requiring reauthorization. Activity is defined as mouse click, keypress, or
::  scrolling in any tab or window of a same-origin browsing context group. Set
::  to zero to disable idle detection.
::
::  Affects: Client
::==============================================================================
:: set STIGMAN_CLIENT_USER_TIMEOUT=

::==============================================================================
:: STIGMAN_CLIENT_WELCOME_IMAGE 
::
::  | No default. | The URL of an image hosted elsewhere that will be rendered
::  in the Home tab Welcome widget. The STIGMan app does not serve the image
::  itself, only the reference to it. The URL should be in relation to and
::  accessible from the client's browser. The image will be scaled to a max
::  width or height of 125 pixels - If no alternate image is specified, the seal
::  of the Department of the Navy (the project sponsor)  will be displayed.
::
::  Affects: Client Appearance
::==============================================================================
:: set STIGMAN_CLIENT_WELCOME_IMAGE =

::==============================================================================
:: STIGMAN_CLIENT_WELCOME_LINK
::
::  | No default. | Value of an optional link that will follow the Welcome
::  message in the Home tab Welcome widget.
::
::  Affects: Client Appearance
::==============================================================================
:: set STIGMAN_CLIENT_WELCOME_LINK=

::==============================================================================
:: STIGMAN_CLIENT_WELCOME_MESSAGE 
::
::  | No default. | Text that will be displayed in the Home tab Welcome widget.
::
::  Affects: Client Appearance
::==============================================================================
:: set STIGMAN_CLIENT_WELCOME_MESSAGE =

::==============================================================================
:: STIGMAN_CLIENT_WELCOME_TITLE 
::
::  | Default: "Support" | The tile that will be displayed for the custom Home
::  tab Welcome message.
::
::  Affects: Client Appearance
::==============================================================================
:: set STIGMAN_CLIENT_WELCOME_TITLE =

::==============================================================================
:: STIGMAN_DB_HOST
::
::  | Default: "localhost" | The database hostname or IP from to the API server
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_HOST=

::==============================================================================
:: STIGMAN_DB_MAX_CONNECTIONS
::
::  | Default: "25" | The maximum size of the database connection pool
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_MAX_CONNECTIONS=

::==============================================================================
:: STIGMAN_DB_PASSWORD
::
::  | No default. | The password used to login to the database
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_PASSWORD=

::==============================================================================
:: STIGMAN_DB_PORT
::
::  | Default: "3306" | The database TCP port relative to the API server
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_PORT=

::==============================================================================
:: STIGMAN_DB_SCHEMA
::
::  | Default: "stigman" | The schema where the STIG Manager object are found
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_SCHEMA=

::==============================================================================
:: STIGMAN_DB_TLS_CA_FILE
::
::  | No default. | An absolute path or a path relative to the API /tls
::  directory that contains the PEM encoded CA certificate used to sign the
::  database TLS certificate. Setting this variable enables TLS connections to
::  the database.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_TLS_CA_FILE=

::==============================================================================
:: STIGMAN_DB_TLS_CERT_FILE
::
::  | No default. | An absolute path or a path relative to the API /tls
::  directory that contains the PEM encoded Client certificate used when
::  authenticating the database client. Additionally requires setting values for
::  "STIGMAN_DB_TLS_CA_FILE" and "STIGMAN_DB_TLS_KEY_FILE".
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_TLS_CERT_FILE=

::==============================================================================
:: STIGMAN_DB_TLS_KEY_FILE
::
::  | No default. | An absolute path or a path relative to the API /tls
::  directory that contains the PEM encoded Client private key used when
::  authenticating the database client. Additionally requires setting values for
::  "STIGMAN_DB_TLS_CA_FILE" and "STIGMAN_DB_TLS_CERT_FILE".
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_TLS_KEY_FILE=

::==============================================================================
:: STIGMAN_DB_USER
::
::  | Default: "stigman" | The user account used to login to the database
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DB_USER=

::==============================================================================
:: STIGMAN_DEPENDENCY_RETRIES
::
::  | Default: "24" | During startup, the number of attempts made to establish
::  connections to the database and OIDC Provider. Retries are made every 5
::  seconds and the API process exits if unsuccessful.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DEPENDENCY_RETRIES=

::==============================================================================
:: STIGMAN_DEV_ALLOW_INSECURE_TOKENS
::
::  | Default: "false" | Controls whether known insecure JWT signing keys are
::  allowed. Only for development/testing purposes. Setting to 'true' is NOT
::  recommended for production environments.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DEV_ALLOW_INSECURE_TOKENS=

::==============================================================================
:: STIGMAN_DEV_LOG_OPT_STATS
::
::  | Default: "true" | Controls whether the API will track API operation
::  statistics used for populating "Requests" portion of "/op/appinfo" response
::  body. Setting to 'false' is NOT recommended for production environments, as
::  this info can be useful for troubleshooting.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DEV_LOG_OPT_STATS=

::==============================================================================
:: STIGMAN_DEV_RESPONSE_VALIDATION
::
::  | Default: "none" | Controls whether the API will perform response
::  validation on API responses. If set to 'logOnly' the API will output log
::  entries indicating deviations from the OAS specification. Intended for
::  development/testing purposes. Available values: "none", "logOnly"
::
::  Affects: API
::==============================================================================
:: set STIGMAN_DEV_RESPONSE_VALIDATION=

::==============================================================================
:: STIGMAN_DOCS_DIRECTORY
::
::  | Default: "./docs" | The location of the documentation files, relative to
::  the API source directory. Note that if running source from a clone of the
::  GitHub repository, the docs are located at `../../docs/_build/html` relative
::  to the API directory.
::
::  Affects: API, Documentation
::==============================================================================
:: set STIGMAN_DOCS_DIRECTORY=

::==============================================================================
:: STIGMAN_DOCS_DISABLED
::
::  | Default: "false" | Whether to *not* serve the project Documentation.
::  NOTE: If you choose to serve the Client from the API container but not the
::  Documentation, the links do the Docs on the home page will not work.
::
::  Affects: Documentation
::==============================================================================
:: set STIGMAN_DOCS_DISABLED=

::==============================================================================
:: STIGMAN_EXPERIMENTAL_APPDATA
::
::  | Default:  "false" | Set to "true" to enable the experimental AppData
::  import/export API endpoints and User Interface.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_EXPERIMENTAL_APPDATA=

::==============================================================================
:: STIGMAN_EXPERIMENTAL_LOGSTREAM
::
::  | Default:  "true" | Set to "false" to disable the experimental WebSocket
::  for streaming API logs and the corresponding User Interface.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_EXPERIMENTAL_LOGSTREAM=

::==============================================================================
:: STIGMAN_LOG_LEVEL
::
::  | Default: "3" | Controls the granularity of the generated log output, from
::  1 to 4. Each level is inclusive of the ones before it. Level 1 will log only
::  errors, level 2 includes warnings, level 3 includes status and transaction
::  logs, and level 4 includes debug-level logs
::
::  Affects: API
::==============================================================================
:: set STIGMAN_LOG_LEVEL=

::==============================================================================
:: STIGMAN_LOG_MODE
::
::  | Default: "combined" | Controls whether the logs will create one “combined”
::  log entry for http requests that includes both the request and response
::  information; or two separate log entries, one for the request and one for
::  the response, that can be correlated via a generated Request GUID in each
::  entry
::
::  Affects: API
::==============================================================================
:: set STIGMAN_LOG_MODE=

::==============================================================================
:: STIGMAN_JWKS_CACHE_MAX_AGE
::
::  | Default: "10" | The time in minutes after which the API's cache of JWT
::  signing keys is deemed stale and the API becomes unavailable. Cache
::  refreshes are scheduled at intervals of half this value and also occur when
::  an unknown signing key is presented. Scheduled refresh failures are retried
::  every 10 seconds.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_JWKS_CACHE_MAX_AGE=

::==============================================================================
:: STIGMAN_JWT_ASSERTION_CLAIM
::
::  | Default: "jti" | The access token claim whose value is the OIDC provider's
::  Assertion ID. Updates to this value trigger the API to update a User's
::  "lastClaims" property. The claim MUST NOT be nested and MUST be a valid
::  ECMAScript identifier. See :ref:`jwt_requirements` for token value format
::  requirements.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_JWT_ASSERTION_CLAIM=

::==============================================================================
:: STIGMAN_JWT_AUD_VALUE
::
::  | No default. | If present, a string which must be included in the access
::  token "aud" claim for requests to endpoints requiring authorization. See
::  :ref:`jwt_requirements` for token value format requirements.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_JWT_AUD_VALUE=

::==============================================================================
:: STIGMAN_JWT_EMAIL_CLAIM
::
::  | Default: "email" | The access token claim whose value is the user's email
::  address. The claim MUST NOT be nested and MUST be a valid ECMAScript
::  identifier. See :ref:`jwt_requirements` for token value format requirements.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_JWT_EMAIL_CLAIM=

::==============================================================================
:: STIGMAN_JWT_NAME_CLAIM
::
::  | Default: "name" | The access token claim whose value is the user's full
::  name. The claim MUST NOT be nested and MUST be a valid ECMAScript
::  identifier. See :ref:`jwt_requirements` for token value format requirements.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_JWT_NAME_CLAIM=

::==============================================================================
:: STIGMAN_JWT_PRIVILEGES_CLAIM
::
::  | Default: "realm_access.roles" | The access token claim whose value is the
::  user's privileges. The claim MAY be nested but SHOULD avoid invalid
::  ECMAScript identifiers. See :ref:`jwt_requirements` for token value format
::  requirements.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_JWT_PRIVILEGES_CLAIM=

::==============================================================================
:: STIGMAN_JWT_SCOPE_CLAIM
::
::  | Default: "scope" | The access token claim whose value is the user's
::  scopes. Some OIDC Providers (Okta, Azure AD) use the claim "scp" to
::  enumerate scopes. The claim MUST NOT be nested and MUST be a valid
::  ECMAScript identifier. See :ref:`jwt_requirements` for token value format
::  requirements.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_JWT_SCOPE_CLAIM=

::==============================================================================
:: STIGMAN_JWT_SERVICENAME_CLAIM
::
::  | Default: "clientId" | The access token claim whose value is the service
::  account's client. The claim MUST NOT be nested and MUST be a valid
::  ECMAScript identifier. See :ref:`jwt_requirements` for token value format
::  requirements.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_JWT_SERVICENAME_CLAIM=

::==============================================================================
:: STIGMAN_JWT_USERNAME_CLAIM
::
::  | Default: "preferred_username" | The access token claim whose value is the
::  user's username. The claim MUST NOT be nested and MUST be a valid ECMAScript
::  identifier. See :ref:`jwt_requirements` for token value format requirements.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_JWT_USERNAME_CLAIM=

::==============================================================================
:: STIGMAN_OIDC_CA_CERTS
::
::  | No default. | The full path to a file with one or more PEM-encoded CA
::  certificates for validating TLS connections to the OIDC Provider.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_OIDC_CA_CERTS=

::==============================================================================
:: STIGMAN_OIDC_PROVIDER
::
::  | Default: "http://localhost:8080/auth/realms/stigman" | The base URL of the
::  OIDC provider issuing signed JWTs for the API.  The string "/.well-
::  known/openid-configuration" will be appended when fetching metadata.
::
::  Affects: API, Client
::==============================================================================
:: set STIGMAN_OIDC_PROVIDER=

::==============================================================================
:: STIGMAN_SWAGGER_ENABLED
::
::  | Default: "false" | Whether to enable the SwaggerUI SPA at /api-docs
::
::  Affects: API
::==============================================================================
:: set STIGMAN_SWAGGER_ENABLED=

::==============================================================================
:: STIGMAN_SWAGGER_OIDC_PROVIDER
::
::  | Default: Value of "STIGMAN_OIDC_PROVIDER" | SwaggerUI override of the base
::  URL of the OIDC provider issuing signed JWTs for the API.  The string
::  "/.well-known/openid-configuration" will be appended by the SwaggerUI when
::  fetching metadata.
::
::  Affects: API
::==============================================================================
:: set STIGMAN_SWAGGER_OIDC_PROVIDER=

::==============================================================================
:: STIGMAN_SWAGGER_REDIRECT
::
::  | Default: "http://localhost:54000/api-docs/oauth2-redirect.html" | The
::  redirect URL sent by SwaggerUI to the OIDC provider when authorizing
::
::  Affects: API
::==============================================================================
:: set STIGMAN_SWAGGER_REDIRECT=

::==============================================================================
:: STIGMAN_SWAGGER_SERVER
::
::  | Default: "http://localhost:54000/api" | The API server URL relative to the
::  SwaggerUI
::
::  Affects: API
::==============================================================================
:: set STIGMAN_SWAGGER_SERVER=

stig-manager-win.exe


================================================
FILE: api/launchers/stig-manager.sh
================================================
#==============================================================================
# STIGMAN_API_ADDRESS
#
#  | Default: "0.0.0.0" | The IP address on which the the API server will listen
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_ADDRESS=

#==============================================================================
# STIGMAN_API_MAX_JSON_BODY
#
#  | Default: "5242880" | The maximum size in bytes of the request body when
#  Content-Type is application/json
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_MAX_JSON_BODY=

#==============================================================================
# STIGMAN_API_MAX_UPLOAD
#
#  | Default: "1073741824" | The maximum size in bytes of the file uploaded with
#  Content-Type multipart/form-data
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_MAX_UPLOAD=

#==============================================================================
# STIGMAN_API_PORT
#
#  | Default: "54000" | The TCP port on which the server will listen
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_PORT=

#==============================================================================
# STIGMAN_API_TLS_CERT_FILE
#
#  | No default. | A absolute path to the file that contains the PEM encoded
#  Server certificate used for TLS. Additionally requires setting
#  "STIGMAN_API_TLS_KEY_FILE" to enable TLS.
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_TLS_CERT_FILE=

#==============================================================================
# STIGMAN_API_TLS_KEY_FILE
#
#  | No default. | A absolute path to the file that contains the PEM encoded
#  Server private key used for TLS. Additionally requires setting
#  "STIGMAN_API_TLS_CERT_FILE" to enable TLS.
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_TLS_KEY_FILE=

#==============================================================================
# STIGMAN_API_TLS_KEY_PASSPHRASE
#
#  | No default. | If necessary, the passphrase that decrypts the PEM encoded
#  Server private key used for TLS. Additionally requires setting
#  "STIGMAN_API_TLS_CERT_FILE" to enable TLS.
#
#  Affects: API
#==============================================================================
# export STIGMAN_API_TLS_KEY_PASSPHRASE=

#==============================================================================
# STIGMAN_CLASSIFICATION
#
#  | Default: "U" | Sets the classification banner, if any. Available values:
#  "NONE" "U" "CUI" "C" "S" "TS" "SCI"
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_CLASSIFICATION=

#==============================================================================
# STIGMAN_CLIENT_ADMIN_TIMEOUT
#
#  | Default: "0" | The maximum time (in minutes) a user with admin privileges
#  can be inactive in the web client before discarding their access token and
#  requiring reauthorization. Activity is defined as mouse click, keypress, or
#  scrolling in any tab or window of a same-origin browsing context group. Set
#  to zero to disable idle detection.
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_ADMIN_TIMEOUT=

#==============================================================================
# STIGMAN_CLIENT_API_BASE
#
#  | Default: "api" | The base URL for Client requests to the API relative to
#  "window.location"
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_API_BASE=

#==============================================================================
# STIGMAN_CLIENT_CONSOLE_MODE
#
#  | Default: "production" | The console mode of the web client, setting to
#  "development" enables console logging which is otherwise disabled
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_CONSOLE_MODE=

#==============================================================================
# STIGMAN_CLIENT_DIRECTORY
#
#  | Default: "./clients" | The location of the web client files, relative to
#  the API source directory. Note that if running source from a clone of the
#  GitHub repository, the client is located at `../../clients` relative to the
#  API directory.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_CLIENT_DIRECTORY=

#==============================================================================
# STIGMAN_CLIENT_DISABLED
#
#  | Default: "false" | Whether to *not* serve the reference web client
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_DISABLED=

#==============================================================================
# STIGMAN_CLIENT_DISPLAY_APPMANAGERS
#
#  | Default: "true" | Whether to display application managers the home page of
#  web client
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_DISPLAY_APPMANAGERS=

#==============================================================================
# STIGMAN_CLIENT_EXTRA_SCOPES
#
#  | No default. | A space separated list of OAuth2 scopes to request in
#  addition to "stig-manager:stig" "stig-manager:stig:read" "stig-
#  manager:collection" "stig-manager:user" "stig-manager:user:read" "stig-
#  manager:op". Some OIDC providers (Okta) generate a refresh token only if the
#  scope "offline_access" is requested
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_EXTRA_SCOPES=

#==============================================================================
# STIGMAN_CLIENT_ID
#
#  | Default: "stig-manager" | The OIDC clientId of the web client
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_ID=

#==============================================================================
# STIGMAN_CLIENT_OIDC_PROVIDER
#
#  | Default: Value of "STIGMAN_OIDC_PROVIDER" | Client override of the base URL
#  of the OIDC provider issuing signed JWTs for the API.  The string "/.well-
#  known/openid-configuration" will be appended by the client when fetching
#  metadata.
#
#  Affects: Client 
#==============================================================================
# export STIGMAN_CLIENT_OIDC_PROVIDER=

#==============================================================================
# STIGMAN_CLIENT_REAUTH_ACTION
#
#  | Default: "popup" | How to prompt for re-authentication when user
#  credentials expire. Available values: "popup", "iframe", "tab", or "reload".
#  See :ref:`stigman_client_reauth_action` in the Authentication document for
#  details.
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_REAUTH_ACTION=

#==============================================================================
# STIGMAN_CLIENT_RESPONSE_MODE
#
#  | Default: "fragment" | The response_mode the web client should specify when
#  requesting an authorization code from the OIDC provider. Available values:
#  "fragment", "query"
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_RESPONSE_MODE=

#==============================================================================
# STIGMAN_CLIENT_SCOPE_PREFIX
#
#  | No default. | String used as a prefix for each scope when authenticating to
#  the OIDC Provider. Some providers (Azure AD) expect scope requests in the
#  format "api://<application_id>/<scope>", where "api://<application_id>/" is
#  the required prefix.
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_SCOPE_PREFIX=

#==============================================================================
# STIGMAN_CLIENT_STATE_EVENTS
#
#  | Default: "true" | Whether the web client listens for server sent events
#  (SSE) about the API state. Should only be disabled temporarily while
#  resolving buffering issues on a reverse proxy.
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_STATE_EVENTS=

#==============================================================================
# STIGMAN_CLIENT_STRICT_PKCE
#
#  | Default: "true" | Whether the web client verifies the OIDC provider is
#  advertising PKCE/S256 support in compliance with RFC 8414. A non-compliant
#  provider supports PKCE/S256 without advertising it. Independent of this
#  value, the web client always exclusively uses PKCE/S256 in the Authorization
#  Code Flow.
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_STRICT_PKCE=

#==============================================================================
# STIGMAN_CLIENT_USER_TIMEOUT
#
#  | Default: "0" | The maximum time (in minutes) a regular user can be inactive
#  in the web client before discarding their access token and requiring
#  reauthorization. Activity is defined as mouse click, keypress, or scrolling
#  in any tab or window of a same-origin browsing context group. Set to zero to
#  disable idle detection.
#
#  Affects: Client
#==============================================================================
# export STIGMAN_CLIENT_USER_TIMEOUT=

#==============================================================================
# STIGMAN_CLIENT_WELCOME_IMAGE 
#
#  | No default. | The URL of an image hosted elsewhere that will be rendered in
#  the Home tab Welcome widget. The STIGMan app does not serve the image itself,
#  only the reference to it. The URL should be in relation to and accessible
#  from the client's browser. The image will be scaled to a max width or height
#  of 125 pixels - If no alternate image is specified, the seal of the
#  Department of the Navy (the project sponsor)  will be displayed.
#
#  Affects: Client Appearance
#==============================================================================
# export STIGMAN_CLIENT_WELCOME_IMAGE =

#==============================================================================
# STIGMAN_CLIENT_WELCOME_LINK
#
#  | No default. | Value of an optional link that will follow the Welcome
#  message in the Home tab Welcome widget.
#
#  Affects: Client Appearance
#==============================================================================
# export STIGMAN_CLIENT_WELCOME_LINK=

#==============================================================================
# STIGMAN_CLIENT_WELCOME_MESSAGE 
#
#  | No default. | Text that will be displayed in the Home tab Welcome widget.
#
#  Affects: Client Appearance
#==============================================================================
# export STIGMAN_CLIENT_WELCOME_MESSAGE =

#==============================================================================
# STIGMAN_CLIENT_WELCOME_TITLE 
#
#  | Default: "Support" | The tile that will be displayed for the custom Home
#  tab Welcome message.
#
#  Affects: Client Appearance
#==============================================================================
# export STIGMAN_CLIENT_WELCOME_TITLE =

#==============================================================================
# STIGMAN_DB_HOST
#
#  | Default: "localhost" | The database hostname or IP from to the API server
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_HOST=

#==============================================================================
# STIGMAN_DB_MAX_CONNECTIONS
#
#  | Default: "25" | The maximum size of the database connection pool
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_MAX_CONNECTIONS=

#==============================================================================
# STIGMAN_DB_PASSWORD
#
#  | No default. | The password used to login to the database
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_PASSWORD=

#==============================================================================
# STIGMAN_DB_PORT
#
#  | Default: "3306" | The database TCP port relative to the API server
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_PORT=

#==============================================================================
# STIGMAN_DB_SCHEMA
#
#  | Default: "stigman" | The schema where the STIG Manager object are found
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_SCHEMA=

#==============================================================================
# STIGMAN_DB_TLS_CA_FILE
#
#  | No default. | An absolute path or a path relative to the API /tls directory
#  that contains the PEM encoded CA certificate used to sign the database TLS
#  certificate. Setting this variable enables TLS connections to the database.
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_TLS_CA_FILE=

#==============================================================================
# STIGMAN_DB_TLS_CERT_FILE
#
#  | No default. | An absolute path or a path relative to the API /tls directory
#  that contains the PEM encoded Client certificate used when authenticating the
#  database client. Additionally requires setting values for
#  "STIGMAN_DB_TLS_CA_FILE" and "STIGMAN_DB_TLS_KEY_FILE".
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_TLS_CERT_FILE=

#==============================================================================
# STIGMAN_DB_TLS_KEY_FILE
#
#  | No default. | An absolute path or a path relative to the API /tls directory
#  that contains the PEM encoded Client private key used when authenticating the
#  database client. Additionally requires setting values for
#  "STIGMAN_DB_TLS_CA_FILE" and "STIGMAN_DB_TLS_CERT_FILE".
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_TLS_KEY_FILE=

#==============================================================================
# STIGMAN_DB_USER
#
#  | Default: "stigman" | The user account used to login to the database
#
#  Affects: API
#==============================================================================
# export STIGMAN_DB_USER=

#==============================================================================
# STIGMAN_DEPENDENCY_RETRIES
#
#  | Default: "24" | During startup, the number of attempts made to establish
#  connections to the database and OIDC Provider. Retries are made every 5
#  seconds and the API process exits if unsuccessful.
#
#  Affects: API
#==============================================================================
# export STIGMAN_DEPENDENCY_RETRIES=

#==============================================================================
# STIGMAN_DEV_ALLOW_INSECURE_TOKENS
#
#  | Default: "false" | Controls whether known insecure JWT signing keys are
#  allowed. Only for development/testing purposes. Setting to 'true' is NOT
#  recommended for production environments.
#
#  Affects: API
#==============================================================================
# export STIGMAN_DEV_ALLOW_INSECURE_TOKENS=

#==============================================================================
# STIGMAN_DEV_LOG_OPT_STATS
#
#  | Default: "true" | Controls whether the API will track API operation
#  statistics used for populating "Requests" portion of "/op/appinfo" response
#  body. Setting to 'false' is NOT recommended for production environments, as
#  this info can be useful for troubleshooting.
#
#  Affects: API
#==============================================================================
# export STIGMAN_DEV_LOG_OPT_STATS=

#==============================================================================
# STIGMAN_DEV_RESPONSE_VALIDATION
#
#  | Default: "none" | Controls whether the API will perform response validation
#  on API responses. If set to 'logOnly' the API will output log entries
#  indicating deviations from the OAS specification. Intended for
#  development/testing purposes. Available values: "none", "logOnly"
#
#  Affects: API
#==============================================================================
# export STIGMAN_DEV_RESPONSE_VALIDATION=

#==============================================================================
# STIGMAN_DOCS_DIRECTORY
#
#  | Default: "./docs" | The location of the documentation files, relative to
#  the API source directory. Note that if running source from a clone of the
#  GitHub repository, the docs are located at `../../docs/_build/html` relative
#  to the API directory.
#
#  Affects: API, Documentation
#==============================================================================
# export STIGMAN_DOCS_DIRECTORY=

#==============================================================================
# STIGMAN_DOCS_DISABLED
#
#  | Default: "false" | Whether to *not* serve the project Documentation.  NOTE:
#  If you choose to serve the Client from the API container but not the
#  Documentation, the links do the Docs on the home page will not work.
#
#  Affects: Documentation
#==============================================================================
# export STIGMAN_DOCS_DISABLED=

#==============================================================================
# STIGMAN_EXPERIMENTAL_APPDATA
#
#  | Default:  "false" | Set to "true" to enable the experimental AppData
#  import/export API endpoints and User Interface.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_EXPERIMENTAL_APPDATA=

#==============================================================================
# STIGMAN_EXPERIMENTAL_LOGSTREAM
#
#  | Default:  "true" | Set to "false" to disable the experimental WebSocket for
#  streaming API logs and the corresponding User Interface.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_EXPERIMENTAL_LOGSTREAM=

#==============================================================================
# STIGMAN_LOG_LEVEL
#
#  | Default: "3" | Controls the granularity of the generated log output, from 1
#  to 4. Each level is inclusive of the ones before it. Level 1 will log only
#  errors, level 2 includes warnings, level 3 includes status and transaction
#  logs, and level 4 includes debug-level logs
#
#  Affects: API
#==============================================================================
# export STIGMAN_LOG_LEVEL=

#==============================================================================
# STIGMAN_LOG_MODE
#
#  | Default: "combined" | Controls whether the logs will create one “combined”
#  log entry for http requests that includes both the request and response
#  information; or two separate log entries, one for the request and one for the
#  response, that can be correlated via a generated Request GUID in each entry
#
#  Affects: API
#==============================================================================
# export STIGMAN_LOG_MODE=

#==============================================================================
# STIGMAN_JWKS_CACHE_MAX_AGE
#
#  | Default: "10" | The time in minutes after which the API's cache of JWT
#  signing keys is deemed stale and the API becomes unavailable. Cache refreshes
#  are scheduled at intervals of half this value and also occur when an unknown
#  signing key is presented. Scheduled refresh failures are retried every 10
#  seconds.
#
#  Affects: API
#==============================================================================
# export STIGMAN_JWKS_CACHE_MAX_AGE=

#==============================================================================
# STIGMAN_JWT_ASSERTION_CLAIM
#
#  | Default: "jti" | The access token claim whose value is the OIDC provider's
#  Assertion ID. Updates to this value trigger the API to update a User's
#  "lastClaims" property. The claim MUST NOT be nested and MUST be a valid
#  ECMAScript identifier. See :ref:`jwt_requirements` for token value format
#  requirements.
#
#  Affects: API
#==============================================================================
# export STIGMAN_JWT_ASSERTION_CLAIM=

#==============================================================================
# STIGMAN_JWT_AUD_VALUE
#
#  | No default. | If present, a string which must be included in the access
#  token "aud" claim for requests to endpoints requiring authorization. See
#  :ref:`jwt_requirements` for token value format requirements.
#
#  Affects: API
#==============================================================================
# export STIGMAN_JWT_AUD_VALUE=

#==============================================================================
# STIGMAN_JWT_EMAIL_CLAIM
#
#  | Default: "email" | The access token claim whose value is the user's email
#  address. The claim MUST NOT be nested and MUST be a valid ECMAScript
#  identifier. See :ref:`jwt_requirements` for token value format requirements.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_JWT_EMAIL_CLAIM=

#==============================================================================
# STIGMAN_JWT_NAME_CLAIM
#
#  | Default: "name" | The access token claim whose value is the user's full
#  name. The claim MUST NOT be nested and MUST be a valid ECMAScript identifier.
#  See :ref:`jwt_requirements` for token value format requirements.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_JWT_NAME_CLAIM=

#==============================================================================
# STIGMAN_JWT_PRIVILEGES_CLAIM
#
#  | Default: "realm_access.roles" | The access token claim whose value is the
#  user's privileges. The claim MAY be nested but SHOULD avoid invalid
#  ECMAScript identifiers. See :ref:`jwt_requirements` for token value format
#  requirements.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_JWT_PRIVILEGES_CLAIM=

#==============================================================================
# STIGMAN_JWT_SCOPE_CLAIM
#
#  | Default: "scope" | The access token claim whose value is the user's scopes.
#  Some OIDC Providers (Okta, Azure AD) use the claim "scp" to enumerate scopes.
#  The claim MUST NOT be nested and MUST be a valid ECMAScript identifier. See
#  :ref:`jwt_requirements` for token value format requirements.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_JWT_SCOPE_CLAIM=

#==============================================================================
# STIGMAN_JWT_SERVICENAME_CLAIM
#
#  | Default: "clientId" | The access token claim whose value is the service
#  account's client. The claim MUST NOT be nested and MUST be a valid ECMAScript
#  identifier. See :ref:`jwt_requirements` for token value format requirements.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_JWT_SERVICENAME_CLAIM=

#==============================================================================
# STIGMAN_JWT_USERNAME_CLAIM
#
#  | Default: "preferred_username" | The access token claim whose value is the
#  user's username. The claim MUST NOT be nested and MUST be a valid ECMAScript
#  identifier. See :ref:`jwt_requirements` for token value format requirements.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_JWT_USERNAME_CLAIM=

#==============================================================================
# STIGMAN_OIDC_CA_CERTS
#
#  | No default. | The full path to a file with one or more PEM-encoded CA
#  certificates for validating TLS connections to the OIDC Provider.
#
#  Affects: API
#==============================================================================
# export STIGMAN_OIDC_CA_CERTS=

#==============================================================================
# STIGMAN_OIDC_PROVIDER
#
#  | Default: "http://localhost:8080/auth/realms/stigman" | The base URL of the
#  OIDC provider issuing signed JWTs for the API.  The string "/.well-
#  known/openid-configuration" will be appended when fetching metadata.
#
#  Affects: API, Client
#==============================================================================
# export STIGMAN_OIDC_PROVIDER=

#==============================================================================
# STIGMAN_SWAGGER_ENABLED
#
#  | Default: "false" | Whether to enable the SwaggerUI SPA at /api-docs
#
#  Affects: API
#==============================================================================
# export STIGMAN_SWAGGER_ENABLED=

#==============================================================================
# STIGMAN_SWAGGER_OIDC_PROVIDER
#
#  | Default: Value of "STIGMAN_OIDC_PROVIDER" | SwaggerUI override of the base
#  URL of the OIDC provider issuing signed JWTs for the API.  The string
#  "/.well-known/openid-configuration" will be appended by the SwaggerUI when
#  fetching metadata.
#
#  Affects: API
#==============================================================================
# export STIGMAN_SWAGGER_OIDC_PROVIDER=

#==============================================================================
# STIGMAN_SWAGGER_REDIRECT
#
#  | Default: "http://localhost:54000/api-docs/oauth2-redirect.html" | The
#  redirect URL sent by SwaggerUI to the OIDC provider when authorizing
#
#  Affects: API
#==============================================================================
# export STIGMAN_SWAGGER_REDIRECT=

#==============================================================================
# STIGMAN_SWAGGER_SERVER
#
#  | Default: "http://localhost:54000/api" | The API server URL relative to the
#  SwaggerUI
#
#  Affects: API
#==============================================================================
# export STIGMAN_SWAGGER_SERVER=

./stig-manager-linuxstatic


================================================
FILE: api/nuwcdivnpt-bot.gpg.asc
================================================
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBGXcsB0BCADIpexQoymA+0AGb9ojtisErQ5cp+xWv3SlPd5kOhuCpbhRhTnB
yQMBr50jqpPZeDtV80V9zyrGg+yLy4MdWM0sBIaW9ixDYeOShRei/GKHVrKxvJI7
YQLZhkng4LqQLgI1AimEzBm5roqfrDQoEnvsj8PbD3iXj7kPrPoUeqZ/3DIVIvKw
DtwfiWb7ycWJjjWe9g9F6T4YLbAidNVwo8QAnGrr7YFKtqhKYpjkK8ZHIDArpzVU
kqTeFJpkC9MchTLmYMLdgjfJAV/NcA7NA+8pUC+jIoT7oLkMgw47iH6ifjarw2+w
HUGuOrhpBF9WCW9OUlJmknjUQEeJeUYn5bXjABEBAAG0Xm51d2NkaXZucHQtYm90
QHVzZXJzLm5vcmVwbHkuZ2l0aHViLmNvbSAoU3RpZ21hbktleSkgPG51d2NkaXZu
cHQtYm90QHVzZXJzLm5vcmVwbHkuZ2l0aHViLmNvbT6JAVQEEwEKAD4WIQRR1CQf
lX8LfXypLo8UO6ovUu6kagUCZdywHQIbLwUJEswDAAULCQgHAgYVCgkICwIEFgID
AQIeAQIXgAAKCRAUO6ovUu6kagZXB/oDogvKYf5vDc8Cu2mrvtGbKO2VXDeLHQJ4
N1X/ZK/Lr4RTZFYDqHJPiqJYlhg58sR+EDsy2HWI3Qxpk7C65SrEF0CwEfNbcHtH
71g7KwHrgDEJw46yCmrt61pjAXVCeokVDPpUozYFoZoCRUHPpWDKEhcR2sizhOeh
0HCOcV2yq308IZKzemAaJU9sAKcjHNB7RQkNbLl50/awINQY0F2kFCUItI8GQ9JA
1+belDh0x5r2dQWCT4O2IIJjUhnKdoMovtp2TlU/ynpKKt781CKF7L548r35eaSM
KRvO2kdsvFuvYe3372kkpkT8edEtxduJnqzZMWyINV43mtCk1GV/uQENBGXcsB0B
CADJtfxgwXWBt3XY0s5iBKPFZFkYEgBKrFJF5YHJV2o8P6+AWIg03KynoJg0yf0h
006tTegUYi53NJpUACUtkRRaDAy4g3xV4bLfK+aN50GWGqIdlIeFeaq93RYLgwL3
GTB/msHoA6CTlQSrSIpjxeqifBPKcklq540AVR4aenntqEjHjpxEjkfzeB0nM1kA
u/4H9N8/B8FM4PqOzF5YlTaTK/UtCJU6TqMTTAg0VMlZjRRItjUUt3Oq+4bOakeX
F+JUiOaYaaYO2OJGiLm9HMuaRSiZGaothkZ/C5LgtkDqIGVcCMgYH0L4l+14IaVJ
iu60rX9Yhca0OOa9gqbR4VQLABEBAAGJAnIEGAEKACYWIQRR1CQflX8LfXypLo8U
O6ovUu6kagUCZdywHQIbLgUJEswDAAFACRAUO6ovUu6kasB0IAQZAQoAHRYhBHS9
Eu1c1I822bsN1VTlnNMfBHn8BQJl3LAdAAoJEFTlnNMfBHn8fAgH/RBVKMde+uEt
18c9gYXLInBu1qvzFIbYpH2hUHXSZcvdaj5AH7i6OF2Ix0jQiaFrnY14FawQkofp
Kd2uYjgyqbdKqn+wTwQhFGgyy5PQBuoLyKmlLXJgIHdsjsmMckDG6R6cA7du4IZx
AUCYsJEoAcnQXuP/XRXDiu8ODpOkMtqnmUn74gDtTALQ5j9mMwVrm7TfT0lFsjj5
W8I2SqZS4YQWKIfdbtUmqHWrzWwVYbzBBkK34YkaFdHd7YpLFSpGUJRgkQfPCu2U
cuO1Tn25VaYaw8xTstk5ul/3sPyuGvbaJnvFBtt+xQgQo6H0+aAbhDDxzxrhtUTg
0MPOw657viZijwf/Vgj1WfpXCxY6v3B4Qghg3dOgsQDAinrWM9xaYueT9bkBWjnD
fZ4Z3iNfUipLFDwJ2XeRBz5MQGwK3d5N11xDMXnYO6IH5m0+0vSLmh12hWQYdGAa
pedI3qbKsZ4/UQfG8ZfKyeBUunZDWNTbR61rFKi+ZNb4W4vF5pVX4kLIIzcJpqa7
8+cUWuD5jUKJt9fZ0cEUlLmZqJ7jsseHE81L2sULIo74p2xgGX1kGpNw5/oyyHRf
/Rf7n9Wqs21lvHK4cqIpmTTUxkEOVomoB7LWlrqhUNMEPmnJes5oWkfN/t1euy8o
OJ/jXthJZVWrxBzZtOmsDMQmJNhTXhgTxlEzvQ==
=b4ti
-----END PGP PUBLIC KEY BLOCK-----

================================================
FILE: api/pkg.config.json
================================================
{
    "name": "stig-manager",
    "pkg": {
        "scripts": ["./source/controllers/**/*.js", "./source/service/**/*.js"],
        "assets": [
            "../client/dist/**/*",
            "../docs/_build/html",
            "./source/service/**/*.sql",
            "./source/node_modules/csv-stringify/**/*",
            "./source/node_modules/swagger-ui-dist/**/*",
            "./source/node_modules/axios/**/*",
            "./source/utils/*.xlsx"
        ],
        "targets": ["node24-win", "node24-linuxstatic"],
        "outputPath": "./bin"
    }
}


================================================
FILE: api/source/README.md
================================================


================================================
FILE: api/source/bootstrap/bootstrapUtils.js
================================================
const path = require('node:path')
const logger = require('../utils/logger')
const extensionCheck = require('./extensionCheck')

function modulePathResolver( handlersPath, route, apiDoc ) {
    const pathKey = route.openApiRoute.substring(route.basePath.length)
    const schema = apiDoc.paths[pathKey][route.method.toLowerCase()]
    const controller = schema.tags[0]
    const operationId = schema['operationId']
    const modulePath = path.join(handlersPath, controller)
    const handler = require(modulePath)
    if (handler[operationId] === undefined) {
      throw new Error(
        `Could not find a [${operationId}] function in ${modulePath} when trying to route [${route.method} ${route.expressRoute}].`,
      )
    }
    return extensionCheck.bind(handler[operationId])
}

function buildResponseValidationConfig(willValidateResponse) {
    if (willValidateResponse){
        return {
            onError: (error, body, req) => {
                logger.writeError('rest', 'responseValidation', {
                    error,
                    request: logger.serializeRequest(req),
                    body
                })
            }
        }
    }
    else {
        return false
    }
}

function logAppConfig(config) {
    logger.writeInfo('bootstrapUtils', 'starting bootstrap', {
      version: config.version,
      env: logger.serializeEnvironment(),
      dirname: __dirname,
      cwd: process.cwd()
    })
    logger.writeInfo('bootstrapUtils', 'configuration', config)
  
}
  
module.exports = {
    modulePathResolver,
    buildResponseValidationConfig,
    logAppConfig
}

================================================
FILE: api/source/bootstrap/client.js
================================================
const express = require('express')
const path = require('path')
const writer = require('../utils/writer')
const logger = require('../utils/logger')
const config = require('../utils/config')

function serveClient(app) {

    if (config.client.disabled) {
        logger.writeDebug('serveClient', 'client', {message: 'client disabled'})
        return
    }
    try {
        serveClientEnv(app)
        serveStaticFiles(app)
        logger.writeDebug('serveClient', 'client', { message: 'succeeded setting up client' })
    }
    catch (err) {
        logger.writeError('serveClient', 'client', {message: err.message, stack: err.stack})
    }
}

function getClientEnv(){
    const envJS = 
    `const STIGMAN = {
        Env: {
            version: "${config.version}",
            consoleMode: "${config.client.consoleMode}",
            apiBase: "${config.client.apiBase}",
            displayAppManagers: ${config.client.displayAppManagers},
            stateEvents: ${config.client.stateEvents},
            welcome: {
                image: "${config.client.welcome.image}",
                title: "${config.client.welcome.title.replace(/"/g, '\\"')}",
                message: "${config.client.welcome.message.replace(/"/g, '\\"')}",
                link: "${config.client.welcome.link}"
            },
            commit: {
                branch: "${config.commit.branch}",
                sha: "${config.commit.sha}",
                tag: "${config.commit.tag}",
                describe: "${config.commit.describe}"
            },
            oauth: {
                authority:  "${config.client.authority}",
                clientId: "${config.client.clientId}",
                extraScopes: "${config.client.extraScopes ?? ''}",
                scopePrefix: "${config.client.scopePrefix ?? ''}",
                responseMode: "${config.client.responseMode}",
                reauthAction: "${config.client.reauthAction}",
                strictPkce: ${config.client.strictPkce},
                audienceValue: "${config.oauth.audienceValue ?? ''}",
                claims: ${JSON.stringify(config.oauth.claims)},
                idleTimeoutUser: ${config.client.idleTimeoutUser},
                idleTimeoutAdmin: ${config.client.idleTimeoutAdmin},
            },
            experimental: {
                appData: "${config.experimental.appData}",
                logStream: "${config.experimental.logStream}"
            }
        }   
    }`
    return envJS
}

function serveClientEnv(app){
    const envJS = getClientEnv()
    app.get('/js/Env.js', function (req, res) {
        req.component = 'static'
        writer.writeWithContentType(res, { payload: envJS, contentType: "application/javascript" })
    })
}

function serveStaticFiles(app){
    const staticPath = path.join(__dirname, "../",  config.client.directory)
    logger.writeDebug('serveStaticFiles', 'client', {client_static: staticPath})
    const expressStatic = express.static(staticPath)

    app.use('/', (req, res, next) => {
        req.component = 'static'
        expressStatic(req, res, next)
    })
}

module.exports = {
    serveClient,
}


================================================
FILE: api/source/bootstrap/dependencies.js
================================================
const logger = require('../utils/logger')
const auth = require('../utils/auth')
const db = require('../service/utils')
const { serializeError } = require('../utils/serializeError')
const state = require('../utils/state')

async function initializeDependencies() {
  try {
      await Promise.all([
          auth.initializeAuth(),
          db.initializeDatabase()
      ])
  } 
  catch (e) {
    logger.writeError('dependencies', 'fail', {message:'Unable to setup dependencies'})
    state.setState('fail')
  }
}

module.exports = {
  initializeDependencies
}


================================================
FILE: api/source/bootstrap/docs.js
================================================

const express = require('express')
const path = require('path')
const fs = require('fs')
const logger = require('../utils/logger')
const config = require('../utils/config')
const swaggerUi = require('swagger-ui-express')
const jsyaml = require('js-yaml')

function serveDocs(app) {
    if (config.docs.disabled) {
        logger.writeDebug('serveDocs', 'client', {message: 'documentation disabled'})
        return
    }
    try {
        app.use('/docs', express.static(path.join(__dirname, "../", config.docs.docsDirectory)))
        logger.writeDebug('serveDocs', 'client', {message: 'succeeded setting up documentation'})
    }
    catch (err) {
        logger.writeError('serveDocs', 'client', {message: err.message, stack: err.stack})
    }
}

function serveApiDocs(app) {
    const oasDoc = getOAS()
    if (config.swaggerUi.enabled) {
        configureSwaggerUI(app, oasDoc)
    }
    else 
    {
        logger.writeDebug('serveApiDocs', 'SwaggerUI', { message: 'Swagger UI is disabled in configuration' })
    }
}

function getOAS(){
    // Read and modify OpenAPI specification
    const apiSpecPath = path.join(__dirname, '../specification/stig-manager.yaml') 
    let spec = fs.readFileSync(apiSpecPath, 'utf8')
    let oasDoc = jsyaml.load(spec)
    // Replace with config values
    oasDoc.info.version = config.version
    oasDoc.servers[0].url = config.swaggerUi.server
    oasDoc.components.securitySchemes.oauth.openIdConnectUrl = `${config.client.authority}/.well-known/openid-configuration`
    config.definition = oasDoc
    return oasDoc
}

function configureSwaggerUI(app, oasDoc){
    app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(oasDoc, null, {
        oauth2RedirectUrl: config.swaggerUi.oauth2RedirectUrl,
        oauth: {
        usePkceWithAuthorizationCodeGrant: true
        }
    }))
    app.get(['/swagger.json','/openapi.json'], function(req, res) {
        res.json(oasDoc)
    })
    logger.writeDebug('configureSwaggerUI', 'client', {message: 'succeeded setting up swagger-ui'})
}

module.exports = { serveDocs, serveApiDocs }

================================================
FILE: api/source/bootstrap/errorHandlers.js
================================================
const logger = require('../utils/logger')
const smErrors = require('../utils/error')
const { serializeError } = require('../utils/serializeError')
const path = require('path')

function configureErrorHandlers(app) {
  // express-openapi-validator does not expose top-level HttpError in their index.js. 
  // We can get it from framework.types.js
  // CAUTION: We break here if express-openapi-validator changes this 
  const eovPath = path.dirname(require.resolve('express-openapi-validator'))
  const eovErrors = require(path.join(eovPath, 'framework', 'types.js'))
  app.use((err, req, res, next) => {
    if (!(err instanceof smErrors.SmError) && !(err instanceof eovErrors.HttpError)) {
      logger.writeError('rest', 'error', {
        request: logger.serializeRequest(req),
        error: serializeError(err)
      })
    }

    res.errorBody = { error: err.message, code: err.code, detail: err.detail}
    if (err.status === 500 || !(err.status)) res.errorBody.stack = err.stack
    if (!res._headerSent) {
      res.status(err.status || 500).header(err.headers).json(res.errorBody)
    }
    else {
      res.write(JSON.stringify(res.errorBody) + '\n')
      res.end()
    }
  })
}

module.exports = configureErrorHandlers


================================================
FILE: api/source/bootstrap/extensionCheck.js
================================================
const SmError = require('../utils/error')

function extensionCheck(req, res, next) {
  if (req.openapi?.schema['x-elevation-required'] && !req.query.elevate) {
    next(new SmError.ElevationError())
    return
  }
  this(req, res, next)
}

module.exports = extensionCheck

================================================
FILE: api/source/bootstrap/middlewares.js
================================================

const path = require('node:path')
const multer  = require('multer')
const express = require('express')
const cors = require('cors')
const { middleware: openApiMiddleware } = require('express-openapi-validator')
const config = require('../utils/config')
const { modulePathResolver, buildResponseValidationConfig } = require('./bootstrapUtils')
const auth = require('../utils/auth')
const configureErrorHandlers = require('./errorHandlers')
const { requestLogger } = require('../utils/logger')
const state = require('../utils/state')
const logger = require('../utils/logger')

function configureMiddleware(app) {

    // Must run before any app.use() call: Express's lazyrouter binds the query
    // parser at the moment the first middleware is registered and ignores
    // later changes.
    app.set('query parser', 'simple')

    const middlewareConfigFunctions = [
      configureMulter,
      configureExpress,
      configureCors,
      configureLogging,
      configureServiceCheck,
      configureAuth,
      configureOpenApi,
      configureErrorHandlers,
  ]

  logger.writeInfo('middleware', 'bootstrap', { message: 'configuring middleware' })

  for (const middlewareConfigFunction of middlewareConfigFunctions) {
      middlewareConfigFunction(app)
  }

  logger.writeInfo('middleware', 'bootstrap', { message: 'middleware configured' })
}

function configureMulter(app) {
    let storage =  multer.memoryStorage()
    const upload = multer({ 
      storage,
      limits: {
        fileSize: parseInt(config.http.maxUpload)
      }
    })
    app.use(upload.single('importFile'))
}

function configureCors(app) {
  app.use(cors())
}

function configureLogging(app) {
  app.use(requestLogger)
}

function configureServiceCheck(app) {
  app.use((req, res, next) => {
    try {
      if (
        state.currentState !== 'available' && req.url.startsWith('/api') && !req.url.startsWith('/api/op/state')) {
        res.status(503).json(state.apiState)
      }
      else {
        next()
      }
    }
    catch (e) {
      next(e)
    }
  })
}

function configureAuth(app) {
  app.use('/api', auth.validateToken)
  app.use('/api', auth.setupUser)
}

function configureExpress(app) {
    app.use(express.urlencoded( {extended: true}))
    app.use(express.json({
        strict: false, // allow root to be any JSON value, per https://datatracker.ietf.org/doc/html/rfc7159#section-2
        limit: parseInt(config.http.maxJsonBody)
    })) //Handle JSON request body
}

function configureOpenApi(app) {
 
  const apiSpecPath = path.join(__dirname, '../specification/stig-manager.yaml')
  app.use( "/api", openApiMiddleware ({
      apiSpec: apiSpecPath,
      validateRequests: {
          coerceTypes: false,
          allowUnknownQueryParameters: false,
      },
      validateResponses: buildResponseValidationConfig(config.settings.responseValidation === "logOnly"),
      validateApiSpec: true,
      $refParser: {
          mode: 'dereference',
      },
      operationHandlers: {
          basePath: path.join(__dirname, '../controllers'),
          resolver: modulePathResolver,
      },
      validateSecurity: {
          handlers:{
          oauth: auth.validateOauthSecurity 
          }
      },
      fileUploader: false
  }))
}

module.exports = configureMiddleware




================================================
FILE: api/source/bootstrap/server.js
================================================
const logger = require('../utils/logger')
const path = require('node:path')
const logSocket = require('../utils/logSocket')
const state = require('../utils/state')
const OperationSvc = require(`../service/OperationService`)
const { serializeError } = require('../utils/serializeError')
const config = require('../utils/config')
const { initializeDependencies } = require('./dependencies')

function setupTls() {
  if (config.http.tls?.key_file && config.http.tls?.cert_file) {
    const fs = require('node:fs')
    let key, cert
    try {
      key = fs.readFileSync(config.http.tls.key_file)
    } catch (e) {
      logger.writeError('server', 'tls_key_read_error', {message: `Failed reading TLS key file: ${config.http.tls.key_file}`, error: serializeError(e)})
      throw e
    }
    try {
      cert = fs.readFileSync(config.http.tls.cert_file)
    } catch (e) {
      logger.writeError('server', 'tls_cert_read_error', {message: `Failed reading TLS certificate file: ${config.http.tls.cert_file}`, error: serializeError(e)})
      throw e
    }
    const tlsOptions = {
      key: key,
      cert: cert
    }
    if (config.http.tls.key_passphrase) {
      tlsOptions.passphrase = config.http.tls.key_passphrase
    }
    return tlsOptions
  } else {
    return null
  }
}

async function startServer(app, startTime) {
  let server
  if (config.http.tls?.key_file && config.http.tls?.cert_file) {
    const https = require('node:https')
    const tlsOptions = setupTls()
    logger.writeInfo('server', 'tls_enabled', {message: 'Creating server with TLS/HTTPS'})
    server = https.createServer(tlsOptions, app)
  } else {
    const http = require('node:http')
    server = http.createServer(app)
  }
  server.on('upgrade', (request) => {
    logger.writeInfo('server', 'upgrade-request', { 
      url: request.url,
      headers: request.headers,
      remoteAddress: request.socket.remoteAddress
    })
  })

  const onListenError = (e) => {
    logger.writeError('server', 'shutdown', { message: `Server failed establishing or while listening on port ${config.http.port}`, error: serializeError(e) })
    state.setState('fail')
  }
  server.on('error', onListenError)

  await logSocket.setupLogSocket(server, path.join(__dirname, '../specification/log-socket.yaml'))

  server.listen(config.http.port, async function () {
    server.removeListener('error', onListenError)
    logger.writeInfo('server', 'listening', {
      port: config.http.port,
      api: '/api',
      client: config.client.disabled ? undefined : '/',
      documentation: config.docs.disabled ? undefined : '/docs',
      swagger: config.swaggerUi.enabled ? '/api-docs' : undefined
    })
    await initializeDependencies()
    // Set/change classification if indicated
    await applyConfigurationSettings()
    logStartupDuration(startTime)
  })
}

async function applyConfigurationSettings() {
  if (config.settings.setClassification) {
    await OperationSvc.setConfigurationItem('classification', config.settings.setClassification)
  }
}

function logStartupDuration(startTime) {
  const endTime = process.hrtime.bigint()
  logger.writeInfo('server', 'started', {
    durationS: Number(endTime - startTime) / 1e9
  })
}

module.exports = startServer


================================================
FILE: api/source/bootstrap/signals.js
================================================
const state = require('../utils/state')
const logger = require('../utils/logger')

// This function sets up signal handlers for the process
// and listens for SIGINT, SIGTERM, and SIGHUP signals
module.exports.setupSignalHandlers = () => {
  const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];

  const signalHandler = (signal) => {
    logger.writeInfo('signals','signal', {signal})
    state.setState('stop')
  }

  for (const signal of signals) {
    process.on(signal, signalHandler)
  }
}


================================================
FILE: api/source/controllers/Asset.js
================================================
'use strict';

const writer = require('../utils/writer')
const config = require('../utils/config')
const escape = require('../utils/escape')
const AssetService = require(`../service/AssetService`)
const CollectionService = require(`../service/CollectionService`)
const Collection = require('./Collection')
const Security = require('../utils/roles')
const dbUtils = require(`../service/utils`)
const {XMLBuilder} = require("fast-xml-parser")
const SmError = require('../utils/error')
const {escapeForXml} = require('../utils/escape')


module.exports.createAsset = async function createAsset (req, res, next) {
  try {
    let projections = req.query.projection
    let assets = req.body
    const collectionId = req.body.collectionId

    const grant = req.userObject.grants[collectionId]
    if (!grant || grant.roleId < 3) throw new SmError.PrivilegeError()

    assets.noncomputing = assets.hasOwnProperty("noncomputing") ? (assets.noncomputing ? 1 : 0) : 0
    assets = [assets]

    const failures = await dbUtils.createAssetValidation({assets, collectionId})

    if (failures.length > 0) {
      throw new SmError.UnprocessableError(failures)
    }

    let assetId
    assetId = await AssetService.createAssets({assets, collectionId, svcStatus: res.svcStatus})
    
    const response = await AssetService.getAsset({
      assetId,
      projections,
      grant,
    })
    res.status(201).json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.createAssets = async function createAssets (req, res, next) {
  try {

    let projections = req.query.projection
    const collectionId  = req.params.collectionId
    let assets = req.body
    let dryRun = req.query.dryRun

    const grant = req.userObject.grants[collectionId]
    if (!grant || grant.roleId < 3) throw new SmError.PrivilegeError()

    // if batch normalize assets (put collection Id into the asset object) and make non-computing a 'boolean int'
    assets = assets.map(asset => ({
      ...asset,
      collectionId,
      noncomputing: asset.hasOwnProperty("noncomputing") ? (asset.noncomputing ? 1 : 0) : 0
    }))

    const failures = await dbUtils.createAssetValidation({assets, collectionId})

    if (failures.length > 0) {
      res.status(200).json({
        error: 'Validation Error',
        detail: failures
      })
      return
    }

    if(dryRun) {
      res.status(204).send()
      return
    }
    
    let assetIds
    assetIds = await AssetService.createAssets( {assets, collectionId, svcStatus: res.svcStatus})
    
    const response = await AssetService.getAssets({
      filter: {
        collectionId: collectionId,
        assetIds,
      },
      projections,
      grant,
    })
    res.status(201).json(response)
  }
  catch (err) {
    next(err)
  }

}

module.exports.deleteAsset = async function deleteAsset (req, res, next) {
  try {
    let projections = req.query.projection
    const { assetId, grant } = await getAssetInfoAndVerifyAccess(req)
    const response = await AssetService.getAsset({assetId, projections, grant})
    await AssetService.deleteAsset(assetId, req.userObject.userId, res.svcStatus)
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.removeStigFromAsset = async function (req, res, next) {
  try {
    let benchmarkId = req.params.benchmarkId
    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req)
    await AssetService.removeStigFromAsset({assetId, benchmarkId, grant, svcStatus: res.svcStatus})
    const response = await AssetService.getStigsByAsset({assetId, grant})
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.removeStigsFromAsset = async function removeStigsFromAsset (req, res, next) {
  try {
    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req)
    await AssetService.removeStigsFromAsset(assetId, grant, res.svcStatus)
    const response = await AssetService.getStigsByAsset({assetId, grant})
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.exportAssets = async function exportAssets (projections, elevate, userObject) {
  // let assets =  await AssetService.getAssets({projections})
  // return assets
} 

module.exports.getAsset = async function (req, res, next) {
  try {
    const assetId = req.params.assetId
    const projections = req.query.projection

    const grant = await dbUtils.getGrantByAssetId(assetId, req.userObject.grants)
    if (!grant) throw new SmError.PrivilegeError()

    const response = await AssetService.getAsset({assetId, projections, grant})
    if (!response) throw new SmError.PrivilegeError()
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getAssets = async function (req, res, next) {
  try {
    const collectionId = req.query.collectionId
    const name = req.query.name
    const nameMatch = req.query['name-match']
    const benchmarkId = req.query.benchmarkId
    const metadata = req.query.metadata
    const labelIds = req.query.labelId
    const labelNames = req.query.labelName
    const labelMatch = req.query.labelMatch
    const projections = req.query.projection
    const grant = req.userObject.grants[collectionId]

    if (!grant) throw new SmError.PrivilegeError('No Grant in Collection')
    
    const response = await AssetService.getAssets({
      filter: {
        collectionId,
        labels: {labelIds, labelNames, labelMatch}, 
        name,
        nameMatch,
        benchmarkId,
        metadata
      },
      projections,
      grant
    })
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getStigsByAsset = async function (req, res, next) {
  try {
    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Restricted)
    const response = await AssetService.getStigsByAsset({assetId, grant} )
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getChecklistByAssetStig = async function getChecklistByAssetStig (req, res, next) {
  try {
    const assetId = req.params.assetId
    const benchmarkId = req.params.benchmarkId
    const revisionStr = req.params.revisionStr
    const format = req.query.format || 'json'
    const projections = req.query.projection

    const access = await dbUtils.getUserAssetStigAccess({assetId, benchmarkId, grants: req.userObject.grants})
    if (access === 'none') throw new SmError.PrivilegeError()

    const checklist = await AssetService.getChecklistByAssetStig(assetId, benchmarkId, revisionStr, format, projections, req.userObject )
    if (format.startsWith('json')) {
      res.json(format === 'json-access' ? {access, checklist} : checklist)
      return
    }
    
    const dateString = escape.filenameComponentFromDate()
    const fileBasename = `${checklist.marking}_${checklist.assetName}-${benchmarkId}-${checklist.revisionStrResolved}`
    if (format === 'cklb') {
      checklist.cklb.title = fileBasename
      writer.writeInlineFile(res, JSON.stringify(checklist.cklb), `${fileBasename}_${dateString}.cklb`, 'application/json')  // revisionStrResolved provides specific rev string, if "latest" was asked for.
    }
    else if (format === 'ckl') {
      const builder = new XMLBuilder({
        attributeNamePrefix : "@_",
        textNodeName : "#text",
        ignoreAttributes : true,
        format: true,
        indentBy: "  ",
        supressEmptyNode: false,
        processEntities: false,
        tagValueProcessor: escapeForXml,
        attrValueProcessor: escapeForXml
      })
      let xml = `<?xml version="1.0" encoding="UTF-8"?>\n<!-- STIG Manager ${config.version} -->\n<!-- Classification: ${checklist.marking} -->\n`
      xml += builder.build(checklist.xmlJs)
      writer.writeInlineFile(res, xml, `${fileBasename}_${dateString}.ckl`, 'application/xml')  // revisionStrResolved provides specific rev string, if "latest" was asked for.
    }
    else if (format === 'xccdf') {
      const builder = new XMLBuilder({
        attributeNamePrefix : "@_",
        textNodeName : "#text",
        ignoreAttributes : false,
        cdataTagName: "__cdata",
        cdataPositionChar: "\\c",
        format: true,
        indentBy: "  ",
        supressEmptyNode: true,
        processEntities: false,
        tagValueProcessor: escapeForXml,
        attrValueProcessor: escapeForXml
      })
      let xml = `<?xml version="1.0" encoding="UTF-8"?>\n<!-- STIG Manager ${config.version} -->\n<!-- Classification: ${checklist.marking} -->\n`
      xml += builder.build(checklist.xmlJs)
      writer.writeInlineFile(res, xml, `${fileBasename}-xccdf_${dateString}.xml`, 'application/xml')  // revisionStrResolved provides specific rev string, if "latest" was asked for.
    }
  }
  catch (err) {
    next(err)
  }
}

module.exports.getChecklistByAsset = async function (req, res, next) {
  try {
    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Restricted)

    const format = req.query.format //default of .ckl provided by EOV

    const assetResponse = await AssetService.getAsset({assetId, projections: ['stigs'], grant} )
    const availableBenchmarkIds = assetResponse.stigs.map( r => r.benchmarkId )
    if (availableBenchmarkIds.length === 0) {
      res.status(204).end()
      return
    }
    const requestedBenchmarkIds = req.query.benchmarkId ?? availableBenchmarkIds
    if (!requestedBenchmarkIds.every( requestedBenchmarkId => availableBenchmarkIds.includes(requestedBenchmarkId))) {
      throw new SmError.ClientError('Asset is not mapped to all requested benchmarkIds')
    }

    const stigs = requestedBenchmarkIds.map( benchmarkId => ({benchmarkId, revisionStr: 'latest'}) )

    const response = await AssetService.getChecklistByAsset(assetId, stigs, format)

    const dateString = escape.filenameComponentFromDate()
    if (format === 'cklb') {
      writer.writeInlineFile(res, JSON.stringify(response.cklb), `${response.assetName}_${dateString}.cklb`, 'application/json') 
    }
    else if (format === 'ckl') {
      const builder = new XMLBuilder({
        attributeNamePrefix : "@_",
        textNodeName : "#text",
        ignoreAttributes : true,
        format: true,
        indentBy: "  ",
        supressEmptyNode: false,
        processEntities: false,
        tagValueProcessor: escapeForXml,
        attrValueProcessor: escapeForXml
      })
      let xml = `<?xml version="1.0" encoding="UTF-8"?>\n<!-- STIG Manager ${config.version} -->\n<!-- Classification: ${response.marking} -->\n`
      xml += builder.build(response.xmlJs)
      writer.writeInlineFile(res, xml, `${response.marking}_${response.assetName}_${dateString}.ckl`, 'application/xml')
    }
  }
  catch (err) {
    next(err)
  }
}

module.exports.getAssetsByStig = async function getAssetsByStig (req, res, next) {
  try {
    const benchmarkId = req.params.benchmarkId
    const labelIds = req.query.labelId
    const labelNames = req.query.labelName
    const labelMatch = req.query.labelMatch
    const projections = req.query.projection

    const {collectionId, grant} = await Collection.getCollectionInfoAndCheckPermission(req, Security.ROLES.Restricted)
    const response = await AssetService.getAssetsByStig({
      collectionId, 
      benchmarkId, 
      labels: {labelIds, labelNames, labelMatch},
      projections, 
      grant
    })
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.replaceAsset = async function replaceAsset (req, res, next) {
  try {
    const projections = req.query.projection
    const body = req.body

    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req)

    const currentAsset = await AssetService.getAsset({assetId, projections, grant})
    // Check if the asset is being transferred
    const transferring = body.collectionId && currentAsset.collection.collectionId !== body.collectionId ? 
      {oldCollectionId: currentAsset.collection.collectionId, newCollectionId: body.collectionId} : null
    if (transferring) {
      // If so, Check if the user has an appropriate grant to the asset's updated collection
      const updatedCollectionGrant = req.userObject.grants[body.collectionId]
      if ( !updatedCollectionGrant || updatedCollectionGrant.roleId < 3 ) {
        throw new SmError.PrivilegeError(`insufficient privilege in destination collection to transfer this asset.`)
      }
    }
    await AssetService.updateAsset({
      assetId,
      body,
      transferring,
      svcStatus: res.svcStatus
    })
    const asset = await AssetService.getAsset({assetId, projections, grant})
    res.json(asset)
  }
  catch (err) {
    next(err)
  }
}

module.exports.attachAssetsToStig = async function attachAssetsToStig (req, res, next) {
  try {
    let benchmarkId = req.params.benchmarkId
    let assetIds = req.body
    let projections = req.query.projection

    const { collectionId, grant } = await Collection.getCollectionInfoAndCheckPermission(req, Security.ROLES.Manage)
    let collection = await CollectionService.getCollection( collectionId, ['assets'], false, req.userObject)
    let collectionAssets = collection.assets.map( a => a.assetId)
    if (assetIds.every( a => collectionAssets.includes(a))) {
      await AssetService.attachAssetsToStig( collectionId, benchmarkId, assetIds )
      let response = await AssetService.getAssetsByStig({collectionId, benchmarkId, projections, grant})
      res.json(response)
    }
    else {
      throw new SmError.PrivilegeError('One or more assetId is not a Collection member.')
    }
  }
  catch (err) {
    next(err)
  }
}

module.exports.attachStigToAsset = async function attachStigToAsset (req, res, next) {
  try {

    let benchmarkId = req.params.benchmarkId
    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Manage)
    await AssetService.attachStigToAsset({
      assetId,
      benchmarkId,
      grant,
      svcStatus: res.svcStatus
    })
    const response = await AssetService.getStigsByAsset({assetId, grant})
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.updateAsset = async function updateAsset (req, res, next) {
  try {
    const projections = req.query.projection
    const body = req.body

    const {assetId, grant} = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Manage)

    // If this user has no grants permitting access to the asset, the response will be undefined
    const currentAsset = await AssetService.getAsset({assetId, projections, grant} )
    // if (!currentAsset) {
    //   throw new SmError.PrivilegeError('User has insufficient privilege to modify this asset.')
    // }
    // // Check if the user has an appropriate grant to the asset's collection
    // const currentCollectionGrant = req.userObject.grants[currentAsset.collection.collectionId]
    // if ( !currentCollectionGrant || currentCollectionGrant.roleId < 3 ) {
    //   throw new SmError.PrivilegeError(`User has insufficient privilege in collectionId ${currentAsset.collection.collectionId} to modify this asset.`)
    // }
    // Check if the asset's collectionId is being changed
    const transferring = body.collectionId && currentAsset.collection.collectionId !== body.collectionId ? 
      {oldCollectionId: currentAsset.collection.collectionId, newCollectionId: body.collectionId} : null
    if (transferring) {
      // If so, Check if the user has an appropriate grant to the asset's updated collection
      const updatedCollectionGrant = req.userObject.grants[body.collectionId]
      if ( !updatedCollectionGrant || updatedCollectionGrant.roleId < 3 ) {
        throw new SmError.PrivilegeError(`User has insufficient privilege in destination collection to transfer this asset.`)
      }
    }
    await AssetService.updateAsset({
      assetId,
      body,
      projections,
      transferring,
      currentCollectionId: currentAsset.collection.collectionId,
      userObject: req.userObject,
      svcStatus: res.svcStatus
    })
    const response = await AssetService.getAsset({assetId, projections, grant})
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getAssetMetadata = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Restricted)
    let result = await AssetService.getAssetMetadata(assetId, req.userObject)
    res.json(result)
  }
  catch (err) {
    next(err)
  }  
}

module.exports.patchAssetMetadata = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req)
    let metadata = req.body
    await AssetService.patchAssetMetadata(assetId, metadata)
    let result = await AssetService.getAssetMetadata(assetId)
    res.json(result)
  }
  catch (err) {
    next(err)
  }  
}

module.exports.putAssetMetadata = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req)
    let body = req.body
    await AssetService.putAssetMetadata(assetId, body)
    let result = await AssetService.getAssetMetadata(assetId)
    res.json(result)
  }
  catch (err) {
    next(err)
  }  
}

module.exports.getAssetMetadataKeys = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Restricted)
    let result = await AssetService.getAssetMetadataKeys(assetId, req.userObject)
    if (!result) {
      throw new SmError.NotFoundError('metadata keys not found')
    }
    res.json(result)
  }
  catch (err) {
    next(err)
  }  
}

module.exports.getAssetMetadataValue = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req, Security.ROLES.Restricted)
    let key = req.params.key
    let result = await AssetService.getAssetMetadataValue(assetId, key, req.userObject)
    if (!result) { 
      throw new SmError.NotFoundError('metadata key not found')
    }
    res.json(result)
  }
  catch (err) {
    next(err)
  }  
}

module.exports.putAssetMetadataValue = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req)
    let key = req.params.key
    let value = req.body

    await AssetService.putAssetMetadataValue(assetId, key, value)
    res.status(204).send()
  }
  catch (err) {
    next(err)
  }  
}


module.exports.deleteAssetMetadataKey = async function (req, res, next) {
  try {
    let { assetId } = await getAssetInfoAndVerifyAccess(req)
    let key = req.params.key

    await AssetService.deleteAssetMetadataKey(assetId, key, req.userObject)
    res.status(204).send()
  }
  catch (err) {
    next(err)
  }  
}

module.exports.patchAssets = async function (req, res, next) {
  try {
    // feature supports delete only
    const collectionId = getCollectionIdAndVerifyAccess(req, Security.ROLES.Manage)
    const patchRequest = req.body

    // optimization: replace below with targeted sql query, select from asset where assetId in ? and collectionId != ?
    const collection = await CollectionService.getCollection( collectionId, ['assets'], false, req.userObject)
    const collectionAssets = collection.assets.map( a => a.assetId)
    if (!patchRequest.assetIds.every( a => collectionAssets.includes(a))) {
      throw new SmError.PrivilegeError('One or more assetId is not a Collection member.')
    }
    await AssetService.deleteAssets(patchRequest.assetIds, req.userObject.userId, res.svcStatus)
    res.json({
      operation: 'deleted',
      assetIds: patchRequest.assetIds
    })
  }
  catch (err) {
    next(err)
  }
}

function getCollectionIdAndVerifyAccess(request, minimumRole = Security.ROLES.Manage) {
  let collectionId = request.query.collectionId
  const grant = request.userObject.grants[collectionId]
  if (grant?.roleId < minimumRole || !grant) {
    throw new SmError.PrivilegeError()
  }
  return collectionId
}

/**
 * Retrieves asset information and verifies user access to the asset which the operation is effecting.
 * Also, ensures that the user has sufficient access level to perform the operation.
 * @param {Object} request - The request object.
 * @returns {Promise<Object>} - A promise that resolves to an object containing the assetId and a grant.
 * @throws {SmError.PrivilegeError} - user does not have sufficient access level or the asset does not exist.
 */
async function getAssetInfoAndVerifyAccess(request, roleId = Security.ROLES.Manage) {
  const assetId = request.params.assetId
  const row = await dbUtils.selectCollectionByAssetId(assetId)
  const grant = request.userObject.grants[row?.collectionId]
  // check if user has sufficient access level
  if (!grant || grant.roleId < roleId) {
    throw new SmError.PrivilegeError("Insufficient access to this asset's collection.")
  }
  return {assetId, grant}
}


================================================
FILE: api/source/controllers/Collection.js
================================================
'use strict';

const writer = require('../utils/writer')
const config = require('../utils/config')
const escape = require('../utils/escape')
const CollectionService = require(`../service/CollectionService`)
const AssetService = require(`../service/AssetService`)
const STIGService = require(`../service/STIGService`)
const UserService = require(`../service/UserService`)
const Serialize = require(`../utils/serializers`)
const Security = require('../utils/roles')
const SmError = require('../utils/error')
const Archiver = require('archiver')
const {XMLBuilder} = require("fast-xml-parser")
const {escapeForXml} = require('../utils/escape')
const dbUtils = require('../service/utils')

module.exports.defaultSettings = {
  fields: {
    detail: {
      enabled: 'always',
      required: 'always'
    },
    comment: {
      enabled: 'findings',
      required: 'findings'
    }
  },
  status: {
    canAccept: true,
    resetCriteria: 'result',
    minAcceptGrant: 3
  },
  history: {
    maxReviews: 5
  },
  importOptions:{
    autoStatus: {
      fail: 'saved',
      notapplicable: 'saved',
      pass: 'saved'
    },
    unreviewed: 'commented',
    unreviewedCommented: 'informational',
    emptyDetail: 'replace',
    emptyComment: 'ignore',
    allowCustom: true
  }
}

module.exports.createCollection = async function createCollection (req, res, next) {
  try {
    const projection = req.query.projection
    const elevate = req.query.elevate
    const body = req.body
    if ( elevate || req.userObject.privileges.create_collection ) {
      if (elevate && (body.settings !== undefined || body.labels !== undefined || body.metadata !== undefined)) {
        throw new SmError.PrivilegeError('Elevated requests cannot set collection settings, labels, or metadata.')
      }
      if (!hasUniqueGrants(body.grants)) {
        throw new SmError.UnprocessableError('Duplicate user or user group in grant array')
      }
      const userIds = body.grants.map(g => g.userId).filter(Boolean)
      const invalidUserIds = await dbUtils.selectInvalidUserIds(userIds)
      if (invalidUserIds.length > 0) {
        throw new SmError.UserInconsistentError()
      }
      try {
        const response = await CollectionService.createCollection( body, projection, req.userObject, res.svcStatus)
        res.status(201).json(response)
      }
      catch (err) {
        // This is MySQL specific, should abstract
        if (err.code === 'ER_DUP_ENTRY') {
          throw new SmError.UnprocessableError('Duplicate name exists.')
        }
        else {
          throw err
        }
      }
    }
    else {
      throw new SmError.PrivilegeError()
    }
  }
  catch (err) {
    next(err)
  }  
}

module.exports.deleteCollection = async function deleteCollection (req, res, next) {
  try {
    const elevate = req.query.elevate
    const projections = req.query.projection
    const { collectionId } = await getCollectionInfoAndCheckPermission(req, Security.ROLES.Owner, true)
    const response = await CollectionService.getCollection(collectionId, projections, elevate, req.userObject)
    await CollectionService.deleteCollection(collectionId, req.userObject.userId)
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.exportCollections = async function exportCollections (projection, elevate, userObject) {
  try {
    return await CollectionService.queryCollections({projection, elevate})
  }
  catch (err) {
    next(err)
  }
} 

module.exports.getChecklistByCollectionStig = async function getChecklistByCollectionStig (req, res, next) {
  try {
    const benchmarkId = req.params.benchmarkId
    const revisionStr = req.params.revisionStr
    const { collectionId } = await getCollectionInfoAndCheckPermission(req, Security.ROLES.Restricted)
    const response = await CollectionService.getChecklistByCollectionStig(collectionId, benchmarkId, revisionStr, req.userObject )
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getCollection = async function getCollection (req, res, next) {
  try {
    const projection = req.query.projection
    const elevate = req.query.elevate
    const { collectionId } = await getCollectionInfoAndCheckPermission(req, Security.ROLES.Restricted, true)
    const response = await CollectionService.getCollection(collectionId, projection, elevate, req.userObject )
    res.status(typeof response === 'undefined' ? 204 : 200).json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getCollections = async function getCollections (req, res, next) {
  try {
    const projections = req.query.projection
    const elevate = req.query.elevate
    const name = req.query.name
    const nameMatch = req.query['name-match']
    const metadata = req.query.metadata
    const response = await CollectionService.queryCollections({
      filter: {name, nameMatch, metadata},
      projections,
      elevate,
      grants: req.userObject.grants,
      userId: req.userObject.userId
    })
    res.json(response)
  }
  catch (err) {
    next(err)
  }
}

module.exports.getFindingsByCollection = async function getFindingsByCollection (req, res, next) {
  try {
    const aggregator = req.query.aggregator
    const benchmarkId = req.query.benchmarkId
    const assetId = req.query.assetId
    const acceptedOnly = req.query.acceptedOnly
    const projections = req.query.proj
Download .txt
gitextract_d5fz8a2i/

├── .dockerignore
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report-form.yml
│   │   └── feature_request.md
│   └── workflows/
│       ├── api-audit-test-coverage-response.yml
│       ├── api-binary-tests.yml
│       ├── api-container-tests.yml
│       ├── api-spec-validation.yml
│       ├── api-state-tests.yml
│       ├── build-binary-artifacts.yml
│       ├── build-client.yml
│       ├── build-docs.yml
│       ├── client-sonarcloud.yml
│       ├── pub-docker.yml
│       └── unit-tests.yml
├── .readthedocs.yml
├── CONTRIBUTING.md
├── CONTRIBUTORS.md
├── Dockerfile
├── INTENT.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── api/
│   ├── README.md
│   ├── bin/
│   │   └── .gitignore
│   ├── build.sh
│   ├── dist/
│   │   └── .gitignore
│   ├── launchers/
│   │   ├── gen-launchers.py
│   │   ├── stig-manager.bat
│   │   └── stig-manager.sh
│   ├── nuwcdivnpt-bot.gpg.asc
│   ├── pkg.config.json
│   └── source/
│       ├── README.md
│       ├── bootstrap/
│       │   ├── bootstrapUtils.js
│       │   ├── client.js
│       │   ├── dependencies.js
│       │   ├── docs.js
│       │   ├── errorHandlers.js
│       │   ├── extensionCheck.js
│       │   ├── middlewares.js
│       │   ├── server.js
│       │   └── signals.js
│       ├── controllers/
│       │   ├── Asset.js
│       │   ├── Collection.js
│       │   ├── Job.js
│       │   ├── Metrics.js
│       │   ├── Operation.js
│       │   ├── Review.js
│       │   ├── STIG.js
│       │   └── User.js
│       ├── healthcheck.js
│       ├── index.js
│       ├── package.json
│       ├── service/
│       │   ├── AssetService.js
│       │   ├── CollectionService.js
│       │   ├── JobService.js
│       │   ├── MetricsService.js
│       │   ├── OperationService.js
│       │   ├── ReviewService.js
│       │   ├── STIGService.js
│       │   ├── UserService.js
│       │   ├── migrations/
│       │   │   ├── 0000.js
│       │   │   ├── 0001.js
│       │   │   ├── 0002.js
│       │   │   ├── 0003.js
│       │   │   ├── 0004.js
│       │   │   ├── 0005.js
│       │   │   ├── 0006.js
│       │   │   ├── 0007.js
│       │   │   ├── 0008.js
│       │   │   ├── 0009.js
│       │   │   ├── 0010.js
│       │   │   ├── 0011.js
│       │   │   ├── 0012.js
│       │   │   ├── 0013.js
│       │   │   ├── 0014.js
│       │   │   ├── 0015.js
│       │   │   ├── 0016.js
│       │   │   ├── 0017.js
│       │   │   ├── 0018.js
│       │   │   ├── 0019.js
│       │   │   ├── 0020.js
│       │   │   ├── 0021.js
│       │   │   ├── 0022.js
│       │   │   ├── 0023.js
│       │   │   ├── 0024.js
│       │   │   ├── 0025.js
│       │   │   ├── 0026.js
│       │   │   ├── 0027.js
│       │   │   ├── 0028.js
│       │   │   ├── 0029.js
│       │   │   ├── 0032.js
│       │   │   ├── 0033.js
│       │   │   ├── 0034.js
│       │   │   ├── 0035.js
│       │   │   ├── 0036.js
│       │   │   ├── 0037.js
│       │   │   ├── 0038.js
│       │   │   ├── 0039.js
│       │   │   ├── 0040.js
│       │   │   ├── 0041.js
│       │   │   ├── 0042.js
│       │   │   ├── 0043.js
│       │   │   ├── 0044.js
│       │   │   ├── 0045.js
│       │   │   ├── 0046.js
│       │   │   ├── lib/
│       │   │   │   ├── MigrationHandler.js
│       │   │   │   ├── mysql-import.js
│       │   │   │   └── umzug-mysql-storage.js
│       │   │   └── sql/
│       │   │       ├── 0000/
│       │   │       │   └── up/
│       │   │       │       ├── 10-stigman-schema.sql
│       │   │       │       ├── 31-stigman-static.sql
│       │   │       │       └── 32-cci-data.sql
│       │   │       ├── 0001/
│       │   │       │   ├── down/
│       │   │       │   │   └── 10-collection-created.sql
│       │   │       │   └── up/
│       │   │       │       └── 10-collection-created.sql
│       │   │       ├── 0002/
│       │   │       │   ├── down/
│       │   │       │   │   └── 10-collection-description.sql
│       │   │       │   └── up/
│       │   │       │       └── 10-collection-description.sql
│       │   │       ├── 0003/
│       │   │       │   └── up/
│       │   │       │       └── 10-asset-mac-fqdn.sql
│       │   │       ├── 0004/
│       │   │       │   └── up/
│       │   │       │       └── 10-user-data.sql
│       │   │       ├── 0005/
│       │   │       │   ├── down/
│       │   │       │   │   └── 10-v-current-rev.sql
│       │   │       │   └── up/
│       │   │       │       └── 10-v-current-rev.sql
│       │   │       ├── 0006/
│       │   │       │   └── up/
│       │   │       │       └── 10-v-current-rev.sql
│       │   │       ├── current/
│       │   │       │   ├── 10-stigman-tables.sql
│       │   │       │   ├── 20-stigman-static.sql
│       │   │       │   └── 31-rev5-cci-data.sql
│       │   │       └── generateSchema.sh
│       │   └── utils.js
│       ├── specification/
│       │   ├── log-socket.yaml
│       │   └── stig-manager.yaml
│       ├── tls/
│       │   └── README.md
│       └── utils/
│           ├── PoolMonitor.js
│           ├── asyncApiValidator.js
│           ├── auth.js
│           ├── buffer-json.js
│           ├── config.js
│           ├── error.js
│           ├── escape.js
│           ├── jwksCache.js
│           ├── klona.js
│           ├── log-schema.json
│           ├── logSocket.js
│           ├── logger.js
│           ├── parsers.js
│           ├── poam-template-mccast.xlsx
│           ├── poam-template.xlsx
│           ├── roles.js
│           ├── serializeError.js
│           ├── serializers.js
│           ├── state.js
│           ├── writer.js
│           └── xlsx-template-js-zip-upgrade/
│               ├── LICENSE
│               ├── README.md
│               ├── lib/
│               │   ├── index.d.ts
│               │   └── index.js
│               └── package.json
├── client/
│   ├── README.md
│   ├── build.sh
│   ├── dist/
│   │   └── .gitignore
│   └── src/
│       ├── css/
│       │   ├── ColumnHeaderGroup.css
│       │   ├── RowEditor.css
│       │   ├── dark-mode.css
│       │   ├── init.css
│       │   ├── jsonview.bundle.css
│       │   └── stigman.css
│       ├── ext/
│       │   ├── INCLUDE_ORDER.txt
│       │   ├── adapter/
│       │   │   └── ext/
│       │   │       ├── ext-base-debug.js
│       │   │       └── ext-base.js
│       │   ├── ext-all-debug-w-comments.js
│       │   ├── ext-all-debug.js
│       │   ├── ext-all.js
│       │   ├── ext.jsb2
│       │   ├── gpl-3.0.txt
│       │   ├── index.html
│       │   ├── license.txt
│       │   ├── release-notes.html
│       │   ├── resources/
│       │   │   ├── charts.swf
│       │   │   ├── css/
│       │   │   │   ├── debug.css
│       │   │   │   ├── ext-all-notheme.css
│       │   │   │   ├── ext-all.css
│       │   │   │   ├── reset-min.css
│       │   │   │   ├── structure/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel-reset.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── pivotgrid.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── reset.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── theme-access/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── theme-gray/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── pivotgrid.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── visual/
│       │   │   │   │   ├── borders.css
│       │   │   │   │   ├── box.css
│       │   │   │   │   ├── button.css
│       │   │   │   │   ├── combo.css
│       │   │   │   │   ├── core.css
│       │   │   │   │   ├── date-picker.css
│       │   │   │   │   ├── dd.css
│       │   │   │   │   ├── debug.css
│       │   │   │   │   ├── dialog.css
│       │   │   │   │   ├── editor.css
│       │   │   │   │   ├── form.css
│       │   │   │   │   ├── grid.css
│       │   │   │   │   ├── layout.css
│       │   │   │   │   ├── list-view.css
│       │   │   │   │   ├── menu.css
│       │   │   │   │   ├── panel.css
│       │   │   │   │   ├── pivotgrid.css
│       │   │   │   │   ├── progress.css
│       │   │   │   │   ├── qtips.css
│       │   │   │   │   ├── resizable.css
│       │   │   │   │   ├── slider.css
│       │   │   │   │   ├── tabs.css
│       │   │   │   │   ├── toolbar.css
│       │   │   │   │   ├── tree.css
│       │   │   │   │   └── window.css
│       │   │   │   ├── xtheme-access.css
│       │   │   │   ├── xtheme-blue.css
│       │   │   │   ├── xtheme-gray.css
│       │   │   │   └── yourtheme.css
│       │   │   ├── expressinstall.swf
│       │   │   └── images/
│       │   │       ├── access/
│       │   │       │   └── form/
│       │   │       │       ├── clear-trigger.psd
│       │   │       │       ├── date-trigger.psd
│       │   │       │       ├── search-trigger.psd
│       │   │       │       └── trigger.psd
│       │   │       ├── default/
│       │   │       │   ├── form/
│       │   │       │   │   ├── clear-trigger.psd
│       │   │       │   │   ├── date-trigger.psd
│       │   │       │   │   ├── search-trigger.psd
│       │   │       │   │   ├── trigger-square.psd
│       │   │       │   │   └── trigger.psd
│       │   │       │   └── window/
│       │   │       │       ├── left-corners.psd
│       │   │       │       ├── left-right.psd
│       │   │       │       ├── right-corners.psd
│       │   │       │       └── top-bottom.psd
│       │   │       └── yourtheme/
│       │   │           ├── README.txt
│       │   │           ├── form/
│       │   │           │   ├── clear-trigger.psd
│       │   │           │   ├── date-trigger.psd
│       │   │           │   ├── search-trigger.psd
│       │   │           │   ├── trigger-square.psd
│       │   │           │   └── trigger.psd
│       │   │           └── window/
│       │   │               ├── left-corners.psd
│       │   │               ├── left-right.psd
│       │   │               ├── right-corners.psd
│       │   │               └── top-bottom.psd
│       │   └── ux/
│       │       ├── BufferView.js
│       │       ├── CenterLayout.js
│       │       ├── CheckColumn.js
│       │       ├── ColumnHeaderGroup.js
│       │       ├── ColumnNodeUI.js
│       │       ├── DataView-more.js
│       │       ├── DataViewTransition.js
│       │       ├── FieldLabeler.js
│       │       ├── FieldReplicator.js
│       │       ├── Focus.js
│       │       ├── GMapPanel.js
│       │       ├── GroupSummary.js
│       │       ├── GroupTab.js
│       │       ├── GroupTabPanel.js
│       │       ├── ItemSelector.js
│       │       ├── LockingGridView.js
│       │       ├── MultiSelect.js
│       │       ├── PagingMemoryProxy.js
│       │       ├── PanelResizer.js
│       │       ├── Portal.js
│       │       ├── PortalColumn.js
│       │       ├── Portlet.js
│       │       ├── ProgressBarPager.js
│       │       ├── Reorderer.js
│       │       ├── RowEditor.js
│       │       ├── RowExpander.js
│       │       ├── RowLayout.js
│       │       ├── SearchField.js
│       │       ├── SelectBox.js
│       │       ├── SlidingPager.js
│       │       ├── Spinner.js
│       │       ├── SpinnerField.js
│       │       ├── Spotlight.js
│       │       ├── TabCloseMenu.js
│       │       ├── TabScrollerMenu.js
│       │       ├── TableGrid.js
│       │       ├── ToolbarDroppable.js
│       │       ├── ToolbarReorderer.js
│       │       ├── XmlTreeLoader.js
│       │       ├── css/
│       │       │   ├── CenterLayout.css
│       │       │   ├── ColumnHeaderGroup.css
│       │       │   ├── ColumnNodeUI.css
│       │       │   ├── GroupSummary.css
│       │       │   ├── GroupTab.css
│       │       │   ├── LockingGridView.css
│       │       │   ├── MultiSelect.css
│       │       │   ├── PanelResizer.css
│       │       │   ├── Portal.css
│       │       │   ├── RowEditor.css
│       │       │   ├── Spinner.css
│       │       │   └── ux-all.css
│       │       ├── fileuploadfield/
│       │       │   ├── FileUploadField.js
│       │       │   └── css/
│       │       │       └── fileuploadfield.css
│       │       ├── gridfilters/
│       │       │   ├── GridFilters.js
│       │       │   ├── css/
│       │       │   │   ├── GridFilters.css
│       │       │   │   └── RangeMenu.css
│       │       │   ├── filter/
│       │       │   │   ├── BooleanFilter.js
│       │       │   │   ├── DateFilter.js
│       │       │   │   ├── Filter.js
│       │       │   │   ├── ListFilter.js
│       │       │   │   ├── NumericFilter.js
│       │       │   │   └── StringFilter.js
│       │       │   └── menu/
│       │       │       ├── ListMenu.js
│       │       │       └── RangeMenu.js
│       │       ├── statusbar/
│       │       │   ├── StatusBar.js
│       │       │   ├── ValidationStatus.js
│       │       │   └── css/
│       │       │       └── statusbar.css
│       │       ├── treegrid/
│       │       │   ├── TreeGrid.js
│       │       │   ├── TreeGridColumnResizer.js
│       │       │   ├── TreeGridColumns.js
│       │       │   ├── TreeGridLoader.js
│       │       │   ├── TreeGridNodeUI.js
│       │       │   ├── TreeGridSorter.js
│       │       │   └── treegrid.css
│       │       ├── ux-all-debug.js
│       │       └── ux-all.js
│       ├── index.html
│       ├── js/
│       │   ├── BufferView.js
│       │   ├── ColumnHeaderGroup.js
│       │   ├── Env.js.example
│       │   ├── ExportButton.js
│       │   ├── FileSaver.js
│       │   ├── FileUploadField.js
│       │   ├── LockingGridView.js
│       │   ├── MessageBox.js
│       │   ├── RowEditor.js
│       │   ├── RowExpander.js
│       │   ├── SM/
│       │   │   ├── Acl.js
│       │   │   ├── ActivityHandler.js
│       │   │   ├── Ajax.js
│       │   │   ├── ApiState.js
│       │   │   ├── AppData.js
│       │   │   ├── AppInfo.js
│       │   │   ├── AssetSelection.js
│       │   │   ├── Attachments.js
│       │   │   ├── BatchReview.js
│       │   │   ├── Cache.js
│       │   │   ├── Checklist.js
│       │   │   ├── Classification.js
│       │   │   ├── CollectionClone.js
│       │   │   ├── CollectionPanel.js
│       │   │   ├── ColumnFilters.js
│       │   │   ├── Error.js
│       │   │   ├── EventDispatcher.js
│       │   │   ├── Exports.js
│       │   │   ├── FindingsPanel.js
│       │   │   ├── FlexboxLayout.js
│       │   │   ├── Global.js
│       │   │   ├── Grant.js
│       │   │   ├── Inventory.js
│       │   │   ├── Job.js
│       │   │   ├── Library.js
│       │   │   ├── LogStream.js
│       │   │   ├── MainPanel.js
│       │   │   ├── Manage.js
│       │   │   ├── MetaPanel.js
│       │   │   ├── NavTree.js
│       │   │   ├── Review.js
│       │   │   ├── ReviewsImport.js
│       │   │   ├── RowEditorToolbar.js
│       │   │   ├── SelectingGridToolbar.js
│       │   │   ├── ServiceWorker.js
│       │   │   ├── StackTrace.js
│       │   │   ├── State.js
│       │   │   ├── StigRevision.js
│       │   │   ├── TipContent.js
│       │   │   ├── TransferAssets.js
│       │   │   ├── User.js
│       │   │   ├── UserGroup.js
│       │   │   └── WhatsNew.js
│       │   ├── collectionAdmin.js
│       │   ├── collectionManager.js
│       │   ├── collectionReview.js
│       │   ├── completionStatus.js
│       │   ├── diff.js
│       │   ├── findingsSummary.js
│       │   ├── init.js
│       │   ├── jsonview.bundle.js
│       │   ├── library.js
│       │   ├── modules/
│       │   │   ├── package.json
│       │   │   └── source-map/
│       │   │       ├── mappings.wasm
│       │   │       └── source-map.js
│       │   ├── overrides.js
│       │   ├── resources-dist.js
│       │   ├── resources.js
│       │   ├── review.js
│       │   ├── stigAdmin.js
│       │   ├── stigman.js
│       │   ├── stigmanUtils.js
│       │   └── workers/
│       │       ├── oidc-worker.js
│       │       ├── service-worker.js
│       │       └── state-worker.js
│       └── reauth.html
├── data/
│   ├── appdata/
│   │   └── README.md
│   └── schemas/
│       ├── Stigman-Model.mwb
│       └── _manifest.json
├── docker-build.sh
├── docs/
│   ├── .nojekyll
│   ├── Dockerfile
│   ├── Makefile
│   ├── STIG-Manager-OSS.ckl
│   ├── _build/
│   │   ├── .gitignore
│   │   └── html/
│   │       └── .gitignore
│   ├── _static/
│   │   └── css/
│   │       ├── custom-pydata-theme.css
│   │       └── custom.css
│   ├── admin-guide/
│   │   ├── admin-guide.rst
│   │   ├── admin-quickstart.rst
│   │   └── index.rst
│   ├── build.sh
│   ├── conf.py
│   ├── features/
│   │   ├── common-tasks.rst
│   │   └── index.rst
│   ├── index.html
│   ├── index.rst
│   ├── installation-and-setup/
│   │   ├── authentication.rst
│   │   ├── data-and-permissions.rst
│   │   ├── db.rst
│   │   ├── environment-variables.rst
│   │   ├── envvars-node.csv
│   │   ├── envvars.csv
│   │   ├── index.rst
│   │   ├── installation-and-setup.rst
│   │   ├── logging.rst
│   │   ├── reverse-proxy.rst
│   │   ├── securing.rst
│   │   └── stigman-asd-full.csv
│   ├── make.bat
│   ├── reference/
│   │   └── index.rst
│   ├── requirements.txt
│   ├── the-project/
│   │   ├── DockerHub_Readme.md
│   │   ├── clients.rst
│   │   ├── contributing.rst
│   │   ├── documentation.rst
│   │   ├── examples.rst
│   │   ├── index.rst
│   │   ├── project-description.rst
│   │   ├── related-repos.rst
│   │   ├── requirements-and-dependencies.rst
│   │   └── testing.rst
│   └── user-guide/
│       ├── Stig-Manager-Asset-Batch-Import.csv
│       ├── index.rst
│       ├── republished-rules.csv
│       ├── review-handling.rst
│       ├── roles-and-access.rst
│       ├── rule-exceptions.rst
│       ├── user-guide.rst
│       └── user-quickstart.rst
├── release-notes.rst
├── root.json
└── test/
    ├── api/
    │   ├── README.md
    │   ├── appdata/
    │   │   ├── appdata-meta-metrics-with-pin.jsonl
    │   │   ├── appdata.jsonl
    │   │   ├── batch-test-data.jsonl
    │   │   ├── user-status-get-post.jsonl
    │   │   └── user-status-patch-put.jsonl
    │   ├── dark.css
    │   ├── form-data-files/
    │   │   ├── U_MS_Windows_10_STIG_V1R23_Manual-xccdf.xml
    │   │   ├── U_RHEL_7_STIG_V3R0-3_Manual-xccdf.xml
    │   │   ├── U_VPN_SRG-OTHER_V1R1_Manual-xccdf.xml
    │   │   ├── U_VPN_SRG-OTHER_V1R1_twoRules-matchingFingerprints.xml
    │   │   ├── U_VPN_SRG_V1R0_Manual-xccdf.xml
    │   │   ├── U_VPN_SRG_V1R1_Manual-xccdf-replace.xml
    │   │   ├── U_VPN_SRG_V1R1_Manual-xccdf.xml
    │   │   └── U_VPN_SRG_V2R3_Manual-xccdf-reviewKeyChange.xml
    │   ├── mocha/
    │   │   ├── cross-boundary/
    │   │   │   └── lvl1.test.js
    │   │   ├── data/
    │   │   │   ├── acl/
    │   │   │   │   ├── directAcl.test.js
    │   │   │   │   ├── directIterations.js
    │   │   │   │   ├── groupAcl.test.js
    │   │   │   │   ├── groupIterations.js
    │   │   │   │   └── referenceData.js
    │   │   │   ├── asset/
    │   │   │   │   ├── assetDelete.test.js
    │   │   │   │   ├── assetGet.test.js
    │   │   │   │   ├── assetPatch.test.js
    │   │   │   │   ├── assetPost.test.js
    │   │   │   │   ├── assetPut.test.js
    │   │   │   │   ├── expectations.js
    │   │   │   │   └── requestBodies.js
    │   │   │   ├── collection/
    │   │   │   │   ├── collectionDelete.test.js
    │   │   │   │   ├── collectionGet.test.js
    │   │   │   │   ├── collectionPatch.test.js
    │   │   │   │   ├── collectionPost.test.js
    │   │   │   │   ├── collectionPut.test.js
    │   │   │   │   ├── expectations.js
    │   │   │   │   └── requestBodies.js
    │   │   │   ├── metrics/
    │   │   │   │   ├── expectations.js
    │   │   │   │   ├── metaMetricsGet.json
    │   │   │   │   ├── metaMetricsGet.test.js
    │   │   │   │   ├── metricsGet.json
    │   │   │   │   └── metricsGet.test.js
    │   │   │   ├── operation/
    │   │   │   │   └── op.test.js
    │   │   │   ├── review/
    │   │   │   │   ├── expectations.js
    │   │   │   │   ├── requestBodies.js
    │   │   │   │   ├── reviewDelete.test.js
    │   │   │   │   ├── reviewGet.test.js
    │   │   │   │   ├── reviewPatch.test.js
    │   │   │   │   ├── reviewPost.test.js
    │   │   │   │   └── reviewPut.test.js
    │   │   │   ├── stig/
    │   │   │   │   ├── expectations.js
    │   │   │   │   └── stigs.test.js
    │   │   │   ├── user/
    │   │   │   │   ├── expectations.js
    │   │   │   │   ├── requestBodies.js
    │   │   │   │   └── user.test.js
    │   │   │   └── user-group/
    │   │   │       ├── requestBodies.js
    │   │   │       └── user-group.test.js
    │   │   ├── integration/
    │   │   │   ├── access.test.js
    │   │   │   ├── aclResolution.test.js
    │   │   │   ├── asset.test.js
    │   │   │   ├── collection.test.js
    │   │   │   ├── deleteHandling.test.js
    │   │   │   ├── expectations.js
    │   │   │   ├── grantChange.test.js
    │   │   │   ├── job.test.js
    │   │   │   ├── logStream.test.js
    │   │   │   ├── metrics.test.js
    │   │   │   ├── resultEngine.test.js
    │   │   │   ├── review.test.js
    │   │   │   ├── revisionPinning.test.js
    │   │   │   ├── roleResolution.test.js
    │   │   │   ├── stig.test.js
    │   │   │   └── userStatus.test.js
    │   │   ├── iterations.js
    │   │   ├── referenceData.js
    │   │   ├── security/
    │   │   │   └── reviewCrossCollectionWrite.test.js
    │   │   ├── testConfig.js
    │   │   └── utils/
    │   │       └── testUtils.js
    │   ├── mock-keycloak/
    │   │   └── auth/
    │   │       └── realms/
    │   │           └── stigman/
    │   │               ├── .well-known/
    │   │               │   └── openid-configuration
    │   │               └── protocol/
    │   │                   └── openid-connect/
    │   │                       └── certs
    │   ├── mock-keycloak-test-cases/
    │   │   ├── no-jwks/
    │   │   │   └── auth/
    │   │   │       └── realms/
    │   │   │           └── stigman/
    │   │   │               ├── .well-known/
    │   │   │               │   └── openid-configuration
    │   │   │               └── protocol/
    │   │   │                   └── openid-connect/
    │   │   │                       └── certs
    │   │   └── secure-kid/
    │   │       └── auth/
    │   │           └── realms/
    │   │               └── stigman/
    │   │                   ├── .well-known/
    │   │                   │   └── openid-configuration
    │   │                   └── protocol/
    │   │                       └── openid-connect/
    │   │                           └── certs
    │   ├── package.json
    │   └── runMocha.sh
    ├── state/
    │   ├── drop-db.sh
    │   ├── mocha/
    │   │   ├── bootstrap.test.js
    │   │   ├── db.test.js
    │   │   ├── jwks.test.js
    │   │   ├── lib.js
    │   │   ├── oidc.test.js
    │   │   └── tokenValidation.test.js
    │   └── package.json
    ├── unit/
    │   ├── mocha/
    │   │   └── asyncApiValidator.test.js
    │   └── package.json
    └── utils/
        ├── appdata-update.js
        ├── mockOidc.js
        └── package.json
Download .txt
SYMBOL INDEX (1301 symbols across 108 files)

FILE: api/source/bootstrap/bootstrapUtils.js
  function modulePathResolver (line 5) | function modulePathResolver( handlersPath, route, apiDoc ) {
  function buildResponseValidationConfig (line 20) | function buildResponseValidationConfig(willValidateResponse) {
  function logAppConfig (line 37) | function logAppConfig(config) {

FILE: api/source/bootstrap/client.js
  function serveClient (line 7) | function serveClient(app) {
  function getClientEnv (line 23) | function getClientEnv(){
  function serveClientEnv (line 66) | function serveClientEnv(app){
  function serveStaticFiles (line 74) | function serveStaticFiles(app){

FILE: api/source/bootstrap/dependencies.js
  function initializeDependencies (line 7) | async function initializeDependencies() {

FILE: api/source/bootstrap/docs.js
  function serveDocs (line 10) | function serveDocs(app) {
  function serveApiDocs (line 24) | function serveApiDocs(app) {
  function getOAS (line 35) | function getOAS(){
  function configureSwaggerUI (line 48) | function configureSwaggerUI(app, oasDoc){

FILE: api/source/bootstrap/errorHandlers.js
  function configureErrorHandlers (line 6) | function configureErrorHandlers(app) {

FILE: api/source/bootstrap/extensionCheck.js
  function extensionCheck (line 3) | function extensionCheck(req, res, next) {

FILE: api/source/bootstrap/middlewares.js
  function configureMiddleware (line 15) | function configureMiddleware(app) {
  function configureMulter (line 42) | function configureMulter(app) {
  function configureCors (line 53) | function configureCors(app) {
  function configureLogging (line 57) | function configureLogging(app) {
  function configureServiceCheck (line 61) | function configureServiceCheck(app) {
  function configureAuth (line 78) | function configureAuth(app) {
  function configureExpress (line 83) | function configureExpress(app) {
  function configureOpenApi (line 91) | function configureOpenApi(app) {

FILE: api/source/bootstrap/server.js
  function setupTls (line 10) | function setupTls() {
  function startServer (line 39) | async function startServer(app, startTime) {
  function applyConfigurationSettings (line 82) | async function applyConfigurationSettings() {
  function logStartupDuration (line 88) | function logStartupDuration(startTime) {

FILE: api/source/controllers/Asset.js
  function getCollectionIdAndVerifyAccess (line 574) | function getCollectionIdAndVerifyAccess(request, minimumRole = Security....
  function getAssetInfoAndVerifyAccess (line 590) | async function getAssetInfoAndVerifyAccess(request, roleId = Security.RO...

FILE: api/source/controllers/Collection.js
  function hasUniqueGrants (line 353) | function hasUniqueGrants(requestedGrants) {
  function requestedOwnerGrantsMatchExisting (line 365) | function requestedOwnerGrantsMatchExisting(requestedGrants, existingGran...
  function getCollectionInfoAndCheckPermission (line 389) | async function getCollectionInfoAndCheckPermission(request, minimumRole ...
  function postArchiveByCollection (line 719) | async function postArchiveByCollection ({format = 'ckl-mono', req, res, ...
  function processAssetStigRequests (line 870) | async function processAssetStigRequests (assetStigRequests, collectionId...
  function progressCb (line 1045) | function progressCb(json) {
  function progressCb (line 1095) | function progressCb(json) {

FILE: api/source/controllers/Metrics.js
  function getCollectionMetrics (line 8) | async function getCollectionMetrics (req, res, next, {style, aggregation...
  function getMetaMetrics (line 40) | async function getMetaMetrics (req, res, next, {style, aggregation, firs...

FILE: api/source/controllers/Operation.js
  function progressCb (line 58) | function progressCb(json) {
  function sendEvent (line 134) | function sendEvent(eventName, data) {

FILE: api/source/controllers/User.js
  function validateCollectionGrants (line 10) | async function validateCollectionGrants(collectionGrants, {elevate}) {
  function putOrPatchUserGroup (line 305) | async function putOrPatchUserGroup (req, res, next) {

FILE: api/source/index.js
  function run (line 30) | async function run() {

FILE: api/source/service/AssetService.js
  function getBenchmarkRevision (line 860) | async function getBenchmarkRevision(connection, benchmarkId, revisionStr) {
  function prefixObjectProperties (line 913) | function prefixObjectProperties(prefix, obj) {
  function generateTargetFacts (line 926) | function generateTargetFacts({metadata, ...assetFields}) {
  function transactionFn (line 1047) | async function transactionFn(connection) {
  function transaction (line 1153) | async function transaction () {
  function transaction (line 1182) | async function transaction () {
  function transaction (line 1210) | async function transaction () {
  function transaction (line 1248) | async function transaction () {
  function transaction (line 1278) | async function transaction () {
  function transaction (line 1499) | async function transaction () {
  function transaction (line 1579) | async function transaction () {

FILE: api/source/service/CollectionService.js
  function transaction (line 462) | async function transaction () {
  function transaction (line 1494) | async function transaction() {
  function queryUnreviewedByCollection (line 1549) | async function queryUnreviewedByCollection ({
  function transaction (line 1703) | async function transaction () {
  function transactionCollection (line 1969) | async function transactionCollection () {
  function transactionReviews (line 1999) | async function transactionReviews () {
  function transaction (line 2386) | async function transaction () {
  function transactionFn (line 2628) | async function transactionFn (connection) {
  function transactionFn (line 2747) | async function transactionFn (connection) {

FILE: api/source/service/JobService.js
  function createEventByJob (line 102) | async function createEventByJob(jobId, eventData) {
  function dropEventByJob (line 134) | async function dropEventByJob(jobId) {
  function getEventNameByJob (line 140) | function getEventNameByJob(jobId) {
  function transactionFn (line 146) | async function transactionFn(connection) {
  function transactionFn (line 175) | async function transactionFn(connection) {

FILE: api/source/service/MetricsService.js
  function genLabelPredicates (line 3) | function genLabelPredicates ({labelNames, labelIds, labelMatch, collecti...

FILE: api/source/service/OperationService.js
  constant BJSON (line 5) | const BJSON = require('../utils/buffer-json')
  class ParseJSONLStream (line 215) | class ParseJSONLStream extends Transform {
    method constructor (line 221) | constructor({jsonParser = JSON.parse, separator = '\n'} = {}) {
    method _transform (line 237) | _transform(chunk, encoding, cb) {
    method _flush (line 268) | _flush(cb) {
  class AppDataQueryStream (line 283) | class AppDataQueryStream extends Transform {
    method constructor (line 290) | constructor({maxValues = 10000, onTablesFn = new Function(), onMigrati...
    method _transform (line 306) | async _transform(chunk, encoding, cb) {
    method _flush (line 347) | _flush(cb) {
    method formatCurrentQuery (line 356) | formatCurrentQuery() {
  function onMigrationFn (line 373) | async function onMigrationFn(record) {
  function migrateTo (line 383) | async function migrateTo(migration = config.lastMigration) {
  function resetDatabase (line 404) | async function resetDatabase() {
  function createChunkedReadable (line 424) | function createChunkedReadable(buffer, chunkSize = 64 * 1024) {
  function createObjectFromKeyValue (line 931) | function createObjectFromKeyValue(data, keyPropertyName, valuePropertyNa...
  function sortObjectByKeys (line 939) | function sortObjectByKeys(obj) {
  function breakOutPrivilegeUsage (line 948) | function breakOutPrivilegeUsage(userInfo) {
  function getNodeValues (line 981) | function getNodeValues() {

FILE: api/source/service/ReviewService.js
  function cteReviewGen (line 20) | function cteReviewGen(obj) {
  function cteAssetGen (line 48) | function cteAssetGen({assetIds = [], benchmarkIds = []}, roleId) {
  function cteRuleGen (line 76) | function cteRuleGen({ruleIds, benchmarkIds, collectionId}) {
  function cteGrantGen (line 96) | function cteGrantGen(roleId) {
  function cteCollectionSettingGen (line 114) | function cteCollectionSettingGen () {
  function genFilter (line 138) | function genFilter(filter) {
  function cteCandidateGen (line 172) | function cteCandidateGen ({skipGrantCheck = false, action, updateFilters...
  function transaction (line 502) | async function transaction () {
  function transaction (line 909) | async function transaction () {
  function transaction (line 1300) | async function transaction () {

FILE: api/source/service/STIGService.js
  function cteStigCollection (line 7) | function cteStigCollection ({elevate = false, unrestrictedCollectionIds ...
  function cteRevCollection (line 40) | function cteRevCollection({elevate = false, unrestrictedCollectionIds = ...
  function parseGrants (line 71) | function parseGrants (grants, elevate = false) {
  function transaction (line 516) | async function transaction() {
  function queriesFromBenchmarkData (line 647) | function queriesFromBenchmarkData(b) {
  function transaction (line 942) | async function transaction () {
  function transaction (line 1020) | async function transaction () {

FILE: api/source/service/UserService.js
  function transaction (line 154) | async function transaction () {
  function transactionFn (line 366) | async function transactionFn (connection) {

FILE: api/source/service/migrations/lib/MigrationHandler.js
  method constructor (line 7) | constructor(upCommands = [], downCommands = []) {
  method up (line 12) | async up(pool, filename) {
  method down (line 33) | async down(pool, filename) {

FILE: api/source/service/migrations/lib/mysql-import.js
  class Importer (line 25) | class Importer{
    method constructor (line 31) | constructor(pool){
    method getImported (line 43) | getImported(){
    method setEncoding (line 53) | setEncoding(encoding){
    method use (line 74) | use(database){
    method import (line 95) | import(...input){
    method disconnect (line 127) | async disconnect(){
    method _importSingleFile (line 149) | _importSingleFile(filepath){
    method _connect (line 183) | async _connect(){
    method _fileExists (line 200) | _fileExists(filepath){
    method _statFile (line 217) | _statFile(filepath){
    method _readDir (line 234) | _readDir(filepath){
    method _getSQLFilePaths (line 251) | _getSQLFilePaths(...paths){
  function slowLoop (line 313) | function slowLoop(items, loopBody) {
  class queryParser (line 324) | class queryParser{
    method constructor (line 326) | constructor(queriesString){
    method parseChar (line 362) | parseChar(char){
    method checkEscapeChar (line 376) | checkEscapeChar(){
    method checkNewDelimiter (line 386) | checkNewDelimiter(char){
    method checkQuote (line 402) | checkQuote(char){
    method checkEndOfQuery (line 412) | checkEndOfQuery(){

FILE: api/source/service/migrations/lib/umzug-mysql-storage.js
  method constructor (line 2) | constructor(options) {
  method createMigrationTable (line 7) | async createMigrationTable () {
  method logMigration (line 16) | async logMigration(migrationName) {
  method unlogMigration (line 26) | async unlogMigration(migrationName) {
  method executed (line 35) | async executed() {

FILE: api/source/service/migrations/sql/0000/up/10-stigman-schema.sql
  type `action` (line 13) | CREATE TABLE `action` (
  type `asset` (line 25) | CREATE TABLE `asset` (
  type `cci` (line 45) | CREATE TABLE `cci` (
  type `cci_reference_map` (line 64) | CREATE TABLE `cci_reference_map` (
  type `check` (line 84) | CREATE TABLE `check` (
  type `collection` (line 95) | CREATE TABLE `collection` (
  type `collection_grant` (line 109) | CREATE TABLE `collection_grant` (
  type `current_group_rule` (line 126) | CREATE TABLE `current_group_rule` (
  type `current_rev` (line 142) | CREATE TABLE `current_rev` (
  type `fix` (line 167) | CREATE TABLE `fix` (
  type `group` (line 178) | CREATE TABLE `group` (
  type `config` (line 190) | CREATE TABLE `config` (
  type `poam_rar_entry` (line 201) | CREATE TABLE `poam_rar_entry` (
  type `reject_string` (line 227) | CREATE TABLE `reject_string` (
  type `result` (line 235) | CREATE TABLE `result` (
  type `rev_group_map` (line 250) | CREATE TABLE `rev_group_map` (
  type `rev_group_rule_check_map` (line 267) | CREATE TABLE `rev_group_rule_check_map` (
  type `rev_group_rule_fix_map` (line 283) | CREATE TABLE `rev_group_rule_fix_map` (
  type `rev_group_rule_map` (line 299) | CREATE TABLE `rev_group_rule_map` (
  type `rev_xml_map` (line 318) | CREATE TABLE `rev_xml_map` (
  type `review` (line 331) | CREATE TABLE `review` (
  type `review_history` (line 358) | CREATE TABLE `review_history` (
  type `review_reject_string_map` (line 381) | CREATE TABLE `review_reject_string_map` (
  type `revision` (line 396) | CREATE TABLE `revision` (
  type `rule` (line 422) | CREATE TABLE `rule` (
  type `rule_cci_map` (line 449) | CREATE TABLE `rule_cci_map` (
  type `rule_oval_map` (line 464) | CREATE TABLE `rule_oval_map` (
  type `severity_cat_map` (line 480) | CREATE TABLE `severity_cat_map` (
  type `stats_asset_stig` (line 494) | CREATE TABLE `stats_asset_stig` (
  type `status` (line 522) | CREATE TABLE `status` (
  type `stig` (line 535) | CREATE TABLE `stig` (
  type `stig_asset_map` (line 547) | CREATE TABLE `stig_asset_map` (
  type `user_data` (line 564) | CREATE TABLE `user_data` (
  type `user_stig_asset_map` (line 590) | CREATE TABLE `user_stig_asset_map` (

FILE: api/source/service/migrations/sql/current/10-stigman-tables.sql
  type `_migrations` (line 20) | CREATE TABLE `_migrations` (
  type `asset` (line 31) | CREATE TABLE `asset` (
  type `cci` (line 58) | CREATE TABLE `cci` (
  type `cci_reference_map` (line 77) | CREATE TABLE `cci_reference_map` (
  type `check_content` (line 97) | CREATE TABLE `check_content` (
  type `collection` (line 110) | CREATE TABLE `collection` (
  type `collection_grant` (line 134) | CREATE TABLE `collection_grant` (
  type `collection_grant_acl` (line 154) | CREATE TABLE `collection_grant_acl` (
  type `collection_label` (line 180) | CREATE TABLE `collection_label` (
  type `collection_label_asset_map` (line 198) | CREATE TABLE `collection_label_asset_map` (
  type `collection_rev_map` (line 214) | CREATE TABLE `collection_rev_map` (
  type `config` (line 230) | CREATE TABLE `config` (
  type `current_rev` (line 241) | CREATE TABLE `current_rev` (
  type `default_rev` (line 269) | CREATE TABLE `default_rev` (
  type `fix_text` (line 328) | CREATE TABLE `fix_text` (
  type `result` (line 398) | CREATE TABLE `result` (
  type `rev_group_rule_cci_map` (line 414) | CREATE TABLE `rev_group_rule_cci_map` (
  type `rev_group_rule_map` (line 428) | CREATE TABLE `rev_group_rule_map` (
  type `review` (line 467) | CREATE TABLE `review` (
  type `review_history` (line 506) | CREATE TABLE `review_history` (
  type `revision` (line 538) | CREATE TABLE `revision` (
  type `rule_version_check_digest` (line 569) | CREATE TABLE `rule_version_check_digest` (
  type `severity_cat_map` (line 582) | CREATE TABLE `severity_cat_map` (
  type `status` (line 596) | CREATE TABLE `status` (
  type `stig` (line 609) | CREATE TABLE `stig` (
  type `stig_asset_map` (line 621) | CREATE TABLE `stig_asset_map` (
  type `task` (line 673) | CREATE TABLE `task` (
  type `task_output` (line 687) | CREATE TABLE `task_output` (
  type `user_data` (line 706) | CREATE TABLE `user_data` (
  type `user_group` (line 726) | CREATE TABLE `user_group` (
  type `user_group_user_map` (line 747) | CREATE TABLE `user_group_user_map` (

FILE: api/source/service/utils.js
  function preflightConnection (line 26) | async function preflightConnection () {
  function getMySqlVersion (line 36) | async function getMySqlVersion () {
  function getTableCount (line 45) | async function getTableCount () {
  function isOkVersion (line 55) | function isOkVersion(version) {
  function doMigrations (line 63) | async function doMigrations() {
  function setupInitialSchema (line 102) | async function setupInitialSchema(){
  function setupSchema (line 123) | async function setupSchema() {
  function resolveDbCertPath (line 148) | function resolveDbCertPath(certPath) {
  function getPoolConfig (line 162) | function getPoolConfig() {
  function patchRemoveConnection (line 207) | function patchRemoveConnection(promisePool) {
  function poolMonitorRetryFn (line 218) | async function poolMonitorRetryFn () {
  function bootstrapRetryFn (line 245) | async function bootstrapRetryFn (fn) {
  function formatSocket (line 263) | function formatSocket(socket) {
  function attachPoolEventHandlers (line 271) | function attachPoolEventHandlers(pool) {

FILE: api/source/utils/PoolMonitor.js
  class PoolMonitor (line 5) | class PoolMonitor {
    method constructor (line 15) | constructor({ pool, state, retryInterval = 40000, retryFn = async () =...
    method onRemove (line 31) | onRemove() {
    method callRetryFn (line 45) | async callRetryFn() {

FILE: api/source/utils/asyncApiValidator.js
  class AsyncApiValidator (line 52) | class AsyncApiValidator {
    method constructor (line 53) | constructor(channels, ajv) {
    method validate (line 66) | validate(key, payload, channel, operation) {
  function resolveRefs (line 92) | function resolveRefs(node, schemas, visited = new Set()) {
  function fromSource (line 125) | function fromSource(schemaPath) {

FILE: api/source/utils/auth.js
  function getClaimByPath (line 18) | function getClaimByPath(obj, path = config.oauth.claims.privilegesRaw) {
  function decodeToken (line 35) | function decodeToken(tokenJWT) {
  function checkInsecureKid (line 44) | function checkInsecureKid(tokenObj) {
  function getSigningKey (line 51) | async function getSigningKey(tokenObj) {
  function verifyToken (line 74) | function verifyToken(tokenJWT, signingKey) {
  function initializeAuth (line 239) | async function initializeAuth() {

FILE: api/source/utils/buffer-json.js
  function stringify (line 1) | function stringify (value, space) {
  function parse (line 5) | function parse (text) {
  function replacer (line 9) | function replacer (key, value) {
  function reviver (line 22) | function reviver (key, value) {
  function isBufferLike (line 37) | function isBufferLike (x) {
  function isArray (line 43) | function isArray (x) {
  function isString (line 47) | function isString (x) {
  function isObject (line 51) | function isObject (x) {

FILE: api/source/utils/config.js
  function formatJsChain (line 124) | function formatJsChain(path) {
  function formatMySqlJsonPath (line 133) | function formatMySqlJsonPath(path) {

FILE: api/source/utils/error.js
  class SmError (line 1) | class SmError extends Error {
    method constructor (line 2) | constructor(message) {
  class ClientError (line 15) | class ClientError extends SmError {
    method constructor (line 16) | constructor(detail) {
  class AuthorizeError (line 23) | class AuthorizeError extends SmError {
    method constructor (line 24) | constructor(detail) {
  class PrivilegeError (line 31) | class PrivilegeError extends SmError {
    method constructor (line 32) | constructor(detail) {
  class NotFoundError (line 39) | class NotFoundError extends SmError {
    method constructor (line 40) | constructor(detail) {
  class UnprocessableError (line 47) | class UnprocessableError extends SmError {
    method constructor (line 48) | constructor(detail) {
  class InternalError (line 55) | class InternalError extends SmError {
    method constructor (line 56) | constructor(error) {
  class OIDCProviderError (line 63) | class OIDCProviderError extends SmError {
    method constructor (line 64) | constructor(detail) {
  class SigningKeyNotFoundError (line 71) | class SigningKeyNotFoundError extends SmError {
    method constructor (line 72) | constructor(detail) {
  class InsecureTokenError (line 79) | class InsecureTokenError extends SmError {
    method constructor (line 80) | constructor(detail) {
  class NoTokenError (line 87) | class NoTokenError extends SmError {
    method constructor (line 88) | constructor(detail) {
  class OutOfScopeError (line 95) | class OutOfScopeError extends SmError {
    method constructor (line 96) | constructor(detail) {
  class ElevationError (line 103) | class ElevationError extends SmError {
    method constructor (line 104) | constructor(detail) {
  class InvalidElevationError (line 111) | class InvalidElevationError extends SmError {
    method constructor (line 112) | constructor(detail) {
  class UserUnavailableError (line 119) | class UserUnavailableError extends SmError {
    method constructor (line 120) | constructor(detail) {
  class UserInconsistentError (line 127) | class UserInconsistentError extends SmError {
    method constructor (line 128) | constructor(detail) {
  class EndpointUnavailableError (line 135) | class EndpointUnavailableError extends SmError {
    method constructor (line 136) | constructor(detail) {
  class ModeLockedError (line 143) | class ModeLockedError extends SmError {
    method constructor (line 144) | constructor(detail) {

FILE: api/source/utils/jwksCache.js
  class JWKSCache (line 8) | class JWKSCache extends EventEmitter {
    method constructor (line 9) | constructor({ jwksUri, caCerts, cacheMaxAge = 60000 }) {
    method getKey (line 21) | getKey(kid) {
    method getKids (line 28) | getKids() {
    method getKidTypes (line 32) | getKidTypes() {
    method setKey (line 40) | setKey(kid, key) {
    method refreshCache (line 45) | async refreshCache(retryOnFailure = true) {
    method clearAllCache (line 59) | clearAllCache() {
    method clearCacheKeepUnknown (line 63) | clearCacheKeepUnknown() {
    method onCacheStale (line 71) | onCacheStale() {
    method request (line 76) | request(url, options) {
    method extractKeysFromJwks (line 178) | extractKeysFromJwks(jwks) {
    method updateCache (line 205) | updateCache() {

FILE: api/source/utils/logSocket.js
  class LogSession (line 11) | class LogSession {
    method constructor (line 12) | constructor(ws, validator) {
  function setupLogSocket (line 265) | async function setupLogSocket (server, schemaPath) {
  function onConnection (line 272) | function onConnection (ws, validator) {

FILE: api/source/utils/logger.js
  function write (line 44) | async function write (level, component, type, data) {
  function sanitizeHeaders (line 62) | function sanitizeHeaders () {
  function serializeRequest (line 79) | function serializeRequest (req) {
  function recordStartTime (line 96) | function recordStartTime () {
  function requestLogger (line 100) | function requestLogger (req, res, next) {
  function serializeEnvironment (line 193) | function serializeEnvironment () {
  function trackOperationStats (line 203) | function trackOperationStats(operationId, durationMs, res) {

FILE: api/source/utils/parsers.js
  function parseRuleDescription (line 59) | function parseRuleDescription (d) {
  function benchmarkDateTo8601 (line 142) | function benchmarkDateTo8601(benchmarkDate) {

FILE: api/source/utils/serializeError.js
  class NonError (line 13) | class NonError extends Error {
    method constructor (line 14) | constructor(message) {
    method _prepareSuperMessage (line 27) | static _prepareSuperMessage(message) {

FILE: api/source/utils/state.js
  class State (line 19) | class State extends EventEmitter {
    method constructor (line 47) | constructor({
    method #emitStateChangedEvent (line 70) | #emitStateChangedEvent() {
    method #emitDependencyChangeEvent (line 74) | #emitDependencyChangeEvent() {
    method #setStateFromDependencyStatus (line 82) | #setStateFromDependencyStatus() {
    method setState (line 95) | setState(state) {
    method setDbStatus (line 107) | setDbStatus(status) {
    method setOidcStatus (line 118) | setOidcStatus(status) {
    method currentState (line 130) | get currentState() {
    method dependencyStatus (line 139) | get dependencyStatus() {
    method dbPool (line 147) | set dbPool(pool) {
    method dbPool (line 156) | get dbPool() {
    method apiState (line 165) | get apiState() {

FILE: api/source/utils/xlsx-template-js-zip-upgrade/lib/index.d.ts
  type TemplatePlaceholder (line 4) | interface TemplatePlaceholder{
  type NamedTable (line 13) | interface NamedTable{
  class Workbook (line 18) | class Workbook
  type GenerateOptions (line 71) | interface GenerateOptions

FILE: client/src/ext/adapter/ext/ext-base-debug.js
  function Base (line 124) | function Base () {
  function fly (line 1692) | function fly(el) {
  function checkRelatedTarget (line 1923) | function checkRelatedTarget(e) {
  function elContains (line 1927) | function elContains(parent, child) {
  function _tryPreloadAttach (line 1943) | function _tryPreloadAttach() {
  function startInterval (line 1981) | function startInterval() {
  function getScroll (line 1991) | function getScroll() {
  function getPageCoord (line 2004) | function getPageCoord (ev, xy) {
  function setHeader (line 2221) | function setHeader(o) {
  function createExceptionObject (line 2240) | function createExceptionObject(tId, callbackArg, isAbort, isTimeout) {
  function initHeader (line 2252) | function initHeader(label, value) {
  function createResponseObject (line 2257) | function createResponseObject(o, callbackArg) {
  function releaseObject (line 2294) | function releaseObject(o) {
  function handleTransactionResponse (line 2303) | function handleTransactionResponse(o, callback, isAbort, isTimeout) {
  function checkResponse (line 2369) | function checkResponse(o, callback, conn, tId, poll, cbTimeout){
  function checkTimeout (line 2382) | function checkTimeout(o, callback){
  function handleReadyState (line 2388) | function handleReadyState(o, callback){
  function asyncRequest (line 2403) | function asyncRequest(method, uri, callback, postData) {
  function getConnectionObject (line 2428) | function getConnectionObject() {
  function createXhrObject (line 2442) | function createXhrObject(transactionId) {
  function parseColor (line 3195) | function parseColor(s) {
  function fnCleanUp (line 3340) | function fnCleanUp() {

FILE: client/src/ext/adapter/ext/ext-base.js
  function k (line 21) | function k(){}
  function c (line 21) | function c(d){if(!b){b=new Ext.Element.Flyweight()}b.dom=d;return b}
  function n (line 21) | function n(F){return !u(F.currentTarget,x.getRelatedTarget(F))}
  function u (line 21) | function u(F,G){if(F&&F.firstChild){while(G){if(G===F){return true}G=G.p...
  function B (line 21) | function B(){var G=false,L=[],J,I,F,H,K=!v||(z>0);if(!A){A=true;for(I=0;...
  function m (line 21) | function m(){if(!d){var F=function(){B()};d=setInterval(F,r)}}
  function C (line 21) | function C(){var F=E.documentElement,G=E.body;if(F&&(F[q]||F[t])){return...
  function j (line 21) | function j(F,G){F=F.browserEvent||F;var H=F["page"+G];if(!H&&H!==0){H=F[...
  function h (line 21) | function h(v){var t=v.conn,w,u={};function s(x,y){for(w in y){if(y.hasOw...
  function e (line 21) | function e(v,u,t,s){return{tId:v,status:t?-1:0,statusText:t?"transaction...
  function j (line 21) | function j(s,t){(k.headers=k.headers||{})[s]=t}
  function p (line 21) | function p(u,y){var C={},x,w=u.conn,A,B,v=w.status==1223;try{x=u.conn.ge...
  function o (line 21) | function o(s){if(s.tId){k.conn[s.tId]=null}s.conn=null;s=null}
  function f (line 21) | function f(x,y,t,s){if(!y){o(x);return}var v,u;try{if(x.conn.status!==un...
  function m (line 21) | function m(u,x,s,w,t,v){if(s&&s.readyState==4){clearInterval(t[w]);t[w]=...
  function r (line 21) | function r(s,t){k.abort(s,t,true)}
  function n (line 21) | function n(u,x){x=x||{};var s=u.conn,w=u.tId,t=k.poll,v=x.timeout||null;...
  function i (line 21) | function i(w,t,v,s){var u=l()||null;if(u){u.conn.open(w,t,true);if(k.use...
  function l (line 21) | function l(){var t;try{if(t=q(k.transactionId)){k.transactionId++}}catch...
  function q (line 21) | function q(v){var s;try{s=new XMLHttpRequest()}catch(u){for(var t=Ext.is...
  function k (line 21) | function k(n){var p=parseInt,o,m=null,q;if(n.length==3){return n}Ext.eac...
  function a (line 21) | function a(){var d=Function.prototype;delete d.createSequence;delete d.d...

FILE: client/src/ext/ext-all-debug-w-comments.js
  function createTargeted (line 380) | function createTargeted(h, o, scope){
  function createBuffered (line 388) | function createBuffered(h, o, l, scope){
  function createSingle (line 395) | function createSingle(h, e, fn, scope){
  function createDelayed (line 402) | function createDelayed(h, o, l, scope){
  function doInsert (line 693) | function doInsert(el, o, returnElement, pos, sibling, append){
  function createHtml (line 699) | function createHtml(o){
  function ieTable (line 746) | function ieTable(depth, s, h, e){
  function insertIntoTable (line 771) | function insertIntoTable(tag, where, el, html) {
  function createContextualFragment (line 805) | function createContextualFragment(html){
  function fn (line 1131) | function fn(m, name){
  function child (line 1321) | function child(parent, index){
  function next (line 1336) | function next(n){
  function prev (line 1342) | function prev(n){
  function children (line 1349) | function children(parent){
  function byClassName (line 1370) | function byClassName(nodeSet, cls){
  function attrValue (line 1383) | function attrValue(n, attr){
  function getNodes (line 1406) | function getNodes(ns, mode, tagName){
  function concat (line 1463) | function concat(a, b){
  function byTag (line 1473) | function byTag(cs, tagName){
  function byId (line 1490) | function byId(cs, id){
  function byAttribute (line 1509) | function byAttribute(cs, attr, value, op, custom){
  function byPseudo (line 1554) | function byPseudo(cs, name, value){
  function nodupIEXml (line 1558) | function nodupIEXml(cs){
  function nodup (line 1576) | function nodup(cs){
  function quickDiffIEXml (line 1609) | function quickDiffIEXml(c1, c2){
  function quickDiff (line 1626) | function quickDiff(c1, c2){
  function quickId (line 1647) | function quickId(ns, mode, root, id){
  function garbageCollect (line 3111) | function garbageCollect(){
  function camelFn (line 3584) | function camelFn(m, a) {
  function chkCache (line 3588) | function chkCache(prop) {
  function after (line 5001) | function after(){
  function argCalc (line 5013) | function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){
  function after (line 5114) | function after(){
  function argCalc (line 5122) | function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){
  function after (line 5196) | function after(){
  function after (line 5256) | function after(){
  function after (line 5324) | function after(){
  function animFn (line 5398) | function animFn(){
  function after (line 5679) | function after(){
  function cb (line 6618) | function cb(){
  function getId (line 7012) | function getId(el){
  function addListener (line 7052) | function addListener(el, ename, fn, task, wrap, scope){
  function doScrollChk (line 7087) | function doScrollChk(){
  function checkReadyState (line 7109) | function checkReadyState(e){
  function checkStyleSheets (line 7123) | function checkStyleSheets(e){
  function OperaDOMContentLoaded (line 7133) | function OperaDOMContentLoaded(e){
  function fireDocReady (line 7138) | function fireDocReady(e){
  function initDocReady (line 7161) | function initDocReady(){
  function createTargeted (line 7195) | function createTargeted(h, o){
  function createBuffered (line 7204) | function createBuffered(h, o, task){
  function createSingle (line 7211) | function createSingle(h, el, ename, fn, scope){
  function createDelayed (line 7218) | function createDelayed(h, o, fn){
  function listen (line 7229) | function listen(element, ename, opt, fn, scope){
  function rFlatten (line 8327) | function rFlatten(a) {
  function doInsert (line 8832) | function doInsert(el, o, returnElement, pos, sibling, append){
  function createDom (line 8850) | function createDom(o, parentNode){
  function fn (line 9023) | function fn(m, name, format, args){
  function fn (line 9062) | function fn(m, name, format, args){
  function getMethodEvent (line 9339) | function getMethodEvent(method){
  function createHandler (line 9443) | function createHandler(ename){
  function fn (line 9898) | function fn(e) {
  function processSuccess (line 11611) | function processSuccess(response){
  function updateComplete (line 11629) | function updateComplete(response, type, success){
  function processFailure (line 11637) | function processFailure(response){
  function xf (line 12224) | function xf(format) {
  function fn (line 14941) | function fn(m, name, format, args, math){
  function codeFn (line 14972) | function codeFn(m, code){
  function transaction (line 37571) | function transaction(records) {
  function toggleGroup (line 49509) | function toggleGroup(btn, state){
  function getHash (line 51090) | function getHash() {
  function doSave (line 51100) | function doSave() {
  function handleStateChange (line 51104) | function handleStateChange(token) {
  function updateIFrame (line 51109) | function updateIFrame (token) {
  function checkIFrame (line 51122) | function checkIFrame() {
  function startUp (line 51161) | function startUp() {
  function callDomLoadFunctions (line 57375) | function callDomLoadFunctions() {
  function addDomLoadEvent (line 57389) | function addDomLoadEvent(fn) {
  function addLoadEvent (line 57402) | function addLoadEvent(fn) {
  function main (line 57427) | function main() {
  function testPlayerVersion (line 57443) | function testPlayerVersion() {
  function matchVersions (line 57475) | function matchVersions() {
  function getObjectById (line 57532) | function getObjectById(objectIdStr) {
  function canExpressInstall (line 57555) | function canExpressInstall() {
  function showExpressInstall (line 57562) | function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
  function displayAltContent (line 57616) | function displayAltContent(obj) {
  function abstractAltContent (line 57638) | function abstractAltContent(obj) {
  function createSWF (line 57662) | function createSWF(attObj, parObj, id) {
  function createObjParam (line 57719) | function createObjParam(el, pName, pValue) {
  function removeSWF (line 57729) | function removeSWF(id) {
  function removeObjectInIE (line 57749) | function removeObjectInIE(id) {
  function getElementById (line 57763) | function getElementById(id) {
  function createElement (line 57772) | function createElement(el) {
  function addListener (line 57779) | function addListener(target, eventType, fn) {
  function hasPlayerVersion (line 57786) | function hasPlayerVersion(rv) {
  function createCSS (line 57797) | function createCSS(sel, decl, media, newStyle) {
  function setVisibility (line 57830) | function setVisibility(id, isVisible) {
  function urlEncodeIfNecessary (line 57843) | function urlEncodeIfNecessary(s) {
  function up (line 59821) | function up(e, m){
  function down (line 59826) | function down(e, m){
  function init (line 59901) | function init(){
  function hideAll (line 59909) | function hideAll(){
  function onHide (line 59921) | function onHide(m){
  function onShow (line 59931) | function onShow(m){
  function onBeforeHide (line 59949) | function onBeforeHide(m){
  function onBeforeShow (line 59960) | function onBeforeShow(m){
  function onMouseDown (line 59970) | function onMouseDown(e){
  function btn (line 67745) | function btn(id, toggle, handler){

FILE: client/src/ext/ext-all-debug.js
  function createTargeted (line 177) | function createTargeted(h, o, scope){
  function createBuffered (line 185) | function createBuffered(h, o, l, scope){
  function createSingle (line 192) | function createSingle(h, e, fn, scope){
  function createDelayed (line 199) | function createDelayed(h, o, l, scope){
  function doInsert (line 363) | function doInsert(el, o, returnElement, pos, sibling, append){
  function createHtml (line 369) | function createHtml(o){
  function ieTable (line 416) | function ieTable(depth, s, h, e){
  function insertIntoTable (line 438) | function insertIntoTable(tag, where, el, html) {
  function createContextualFragment (line 469) | function createContextualFragment(html){
  function fn (line 663) | function fn(m, name){
  function child (line 740) | function child(parent, index){
  function next (line 755) | function next(n){
  function prev (line 761) | function prev(n){
  function children (line 768) | function children(parent){
  function byClassName (line 789) | function byClassName(nodeSet, cls){
  function attrValue (line 802) | function attrValue(n, attr){
  function getNodes (line 825) | function getNodes(ns, mode, tagName){
  function concat (line 882) | function concat(a, b){
  function byTag (line 892) | function byTag(cs, tagName){
  function byId (line 909) | function byId(cs, id){
  function byAttribute (line 928) | function byAttribute(cs, attr, value, op, custom){
  function byPseudo (line 973) | function byPseudo(cs, name, value){
  function nodupIEXml (line 977) | function nodupIEXml(cs){
  function nodup (line 995) | function nodup(cs){
  function quickDiffIEXml (line 1028) | function quickDiffIEXml(c1, c2){
  function quickDiff (line 1045) | function quickDiff(c1, c2){
  function quickId (line 1066) | function quickId(ns, mode, root, id){
  function garbageCollect (line 2422) | function garbageCollect(){
  function camelFn (line 2744) | function camelFn(m, a) {
  function chkCache (line 2748) | function chkCache(prop) {
  function after (line 3665) | function after(){
  function argCalc (line 3677) | function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){
  function after (line 3753) | function after(){
  function argCalc (line 3761) | function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){
  function after (line 3816) | function after(){
  function after (line 3857) | function after(){
  function after (line 3902) | function after(){
  function animFn (line 3956) | function animFn(){
  function after (line 4118) | function after(){
  function cb (line 4735) | function cb(){
  function getId (line 4977) | function getId(el){
  function addListener (line 5017) | function addListener(el, ename, fn, task, wrap, scope){
  function doScrollChk (line 5047) | function doScrollChk(){
  function checkReadyState (line 5063) | function checkReadyState(e){
  function checkStyleSheets (line 5077) | function checkStyleSheets(e){
  function OperaDOMContentLoaded (line 5087) | function OperaDOMContentLoaded(e){
  function fireDocReady (line 5092) | function fireDocReady(e){
  function initDocReady (line 5115) | function initDocReady(){
  function createTargeted (line 5144) | function createTargeted(h, o){
  function createBuffered (line 5153) | function createBuffered(h, o, task){
  function createSingle (line 5160) | function createSingle(h, el, ename, fn, scope){
  function createDelayed (line 5167) | function createDelayed(h, o, fn){
  function listen (line 5178) | function listen(element, ename, opt, fn, scope){
  function rFlatten (line 5976) | function rFlatten(a) {
  function doInsert (line 6290) | function doInsert(el, o, returnElement, pos, sibling, append){
  function createDom (line 6308) | function createDom(o, parentNode){
  function fn (line 6417) | function fn(m, name, format, args){
  function fn (line 6456) | function fn(m, name, format, args){
  function getMethodEvent (line 6733) | function getMethodEvent(method){
  function createHandler (line 6837) | function createHandler(ename){
  function fn (line 7240) | function fn(e) {
  function processSuccess (line 8452) | function processSuccess(response){
  function updateComplete (line 8470) | function updateComplete(response, type, success){
  function processFailure (line 8478) | function processFailure(response){
  function xf (line 8726) | function xf(format) {
  function fn (line 10388) | function fn(m, name, format, args, math){
  function codeFn (line 10419) | function codeFn(m, code){
  function transaction (line 24478) | function transaction(records) {
  function toggleGroup (line 32008) | function toggleGroup(btn, state){
  function getHash (line 32929) | function getHash() {
  function doSave (line 32939) | function doSave() {
  function handleStateChange (line 32943) | function handleStateChange(token) {
  function updateIFrame (line 32948) | function updateIFrame (token) {
  function checkIFrame (line 32961) | function checkIFrame() {
  function startUp (line 33000) | function startUp() {
  function callDomLoadFunctions (line 37449) | function callDomLoadFunctions() {
  function addDomLoadEvent (line 37463) | function addDomLoadEvent(fn) {
  function addLoadEvent (line 37473) | function addLoadEvent(fn) {
  function main (line 37496) | function main() {
  function testPlayerVersion (line 37506) | function testPlayerVersion() {
  function matchVersions (line 37537) | function matchVersions() {
  function getObjectById (line 37594) | function getObjectById(objectIdStr) {
  function canExpressInstall (line 37612) | function canExpressInstall() {
  function showExpressInstall (line 37617) | function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
  function displayAltContent (line 37670) | function displayAltContent(obj) {
  function abstractAltContent (line 37692) | function abstractAltContent(obj) {
  function createSWF (line 37715) | function createSWF(attObj, parObj, id) {
  function createObjParam (line 37772) | function createObjParam(el, pName, pValue) {
  function removeSWF (line 37780) | function removeSWF(id) {
  function removeObjectInIE (line 37800) | function removeObjectInIE(id) {
  function getElementById (line 37813) | function getElementById(id) {
  function createElement (line 37822) | function createElement(el) {
  function addListener (line 37827) | function addListener(target, eventType, fn) {
  function hasPlayerVersion (line 37833) | function hasPlayerVersion(rv) {
  function createCSS (line 37842) | function createCSS(sel, decl, media, newStyle) {
  function setVisibility (line 37875) | function setVisibility(id, isVisible) {
  function urlEncodeIfNecessary (line 37887) | function urlEncodeIfNecessary(s) {
  function up (line 39300) | function up(e, m){
  function down (line 39305) | function down(e, m){
  function init (line 39376) | function init(){
  function hideAll (line 39384) | function hideAll(){
  function onHide (line 39396) | function onHide(m){
  function onShow (line 39406) | function onShow(m){
  function onBeforeHide (line 39424) | function onBeforeHide(m){
  function onBeforeShow (line 39435) | function onBeforeShow(m){
  function onMouseDown (line 39445) | function onMouseDown(e){
  function btn (line 44491) | function btn(id, toggle, handler){

FILE: client/src/ext/ext-all.js
  function e (line 21) | function e(l,m,k){return function(){if(m.target==arguments[0]){l.apply(k...
  function b (line 21) | function b(n,p,k,m){k.task=new h.DelayedTask();return function(){k.task....
  function c (line 21) | function c(m,n,l,k){return function(){n.removeListener(l,k);return m.app...
  function a (line 21) | function a(n,p,k,m){return function(){var l=new h.DelayedTask(),o=Array....
  function h (line 21) | function h(B,D,C,E,A,y){var z=r.insertHtml(E,Ext.getDom(B),u(D));return ...
  function u (line 21) | function u(D){var z="",y,C,B,E;if(typeof D=="string"){z=D}else{if(Ext.is...
  function g (line 21) | function g(F,C,B,D){x.innerHTML=[C,B,D].join("");var y=-1,A=x,z;while(++...
  function e (line 21) | function e(y,z,B,A){var C,D;x=x||document.createElement("div");if(y=="td...
  function s (line 21) | function s(A){var D=document.createElement("div"),y=document.createDocum...
  function fn (line 21) | function fn(m,name){name="values['"+name+"']";return"'"+sep+"("+name+" =...
  function child (line 21) | function child(parent,index){var i=0,n=parent.firstChild;while(n){if(n.n...
  function next (line 21) | function next(n){while((n=n.nextSibling)&&n.nodeType!=1){}return n}
  function prev (line 21) | function prev(n){while((n=n.previousSibling)&&n.nodeType!=1){}return n}
  function children (line 21) | function children(parent){var n=parent.firstChild,nodeIndex=-1,nextNode;...
  function byClassName (line 21) | function byClassName(nodeSet,cls){if(!cls){return nodeSet}var result=[],...
  function attrValue (line 21) | function attrValue(n,attr){if(!n.tagName&&typeof n.length!="undefined"){...
  function getNodes (line 21) | function getNodes(ns,mode,tagName){var result=[],ri=-1,cs;if(!ns){return...
  function concat (line 21) | function concat(a,b){if(b.slice){return a.concat(b)}for(var i=0,l=b.leng...
  function byTag (line 21) | function byTag(cs,tagName){if(cs.tagName||cs==document){cs=[cs]}if(!tagN...
  function byId (line 21) | function byId(cs,id){if(cs.tagName||cs==document){cs=[cs]}if(!id){return...
  function byAttribute (line 21) | function byAttribute(cs,attr,value,op,custom){var result=[],ri=-1,useGet...
  function byPseudo (line 21) | function byPseudo(cs,name,value){return Ext.DomQuery.pseudos[name](cs,va...
  function nodupIEXml (line 21) | function nodupIEXml(cs){var d=++key,r;cs[0].setAttribute("_nodup",d);r=[...
  function nodup (line 21) | function nodup(cs){if(!cs){return[]}var len=cs.length,c,i,r=cs,cj,ri=-1;...
  function quickDiffIEXml (line 21) | function quickDiffIEXml(c1,c2){var d=++key,r=[];for(var i=0,len=c1.lengt...
  function quickDiff (line 21) | function quickDiff(c1,c2){var len1=c1.length,d=++key,r=[];if(!len1){retu...
  function quickId (line 21) | function quickId(ns,mode,root,id){if(ns==root){var d=root.ownerDocument|...
  function j (line 21) | function j(){if(!Ext.enableGarbageCollector){clearInterval(e.collectorTh...
  function p (line 21) | function p(F,G){return G.charAt(1).toUpperCase()}
  function v (line 21) | function v(F){return h[F]||(h[F]=F=="float"?(A.cssFloat?"cssFloat":"styl...
  function P (line 21) | function P(){p(G).fxUnwrap(D,B.pos,E);M.width=B.width;M.height=B.height;...
  function Q (line 21) | function Q(U,R,V,S,X,Z,ac,ab,aa,W,T){var Y={};p(U).setWidth(V).setHeight...
  function M (line 21) | function M(){D.useDisplay?p(E).setDisplayed(t):p(E).hide();p(E).fxUnwrap...
  function N (line 21) | function N(O,W,U,X,S,V,R,T,Q){var P={};O[W]=O[U]="0";P[X]=S;if(V){P[V]=R...
  function I (line 21) | function I(){H.useDisplay?p(G).setDisplayed(t):p(G).hide();p(G).clearOpa...
  function G (line 21) | function G(){F.useDisplay?p(E).setDisplayed(t):p(E).hide();p(E).clearOpa...
  function I (line 21) | function I(){G.style[B]=E;p(G).afterFx(H)}
  function K (line 21) | function K(){var M=Ext.isBorderBox?2:1;F=C.anim({top:{from:J.y,to:J.y-20...
  function L (line 21) | function L(){C.useDisplay?p(D).setDisplayed(t):p(D).hide();p(D).clearOpa...
  function s (line 21) | function s(){var x=this,w={responseText:"",responseXML:null,argument:q.a...
  function n (line 21) | function n(E){var H=false,D=0,C=u.length,F=false,G;if(E){if(E.getElement...
  function m (line 21) | function m(E,G,J,F,D,L){E=Ext.getDom(E);var C=n(E),K=Ext.elCache[C].even...
  function d (line 21) | function d(){if(window!=top){return false}try{c.documentElement.doScroll...
  function B (line 21) | function B(C){if(Ext.isIE9m&&d()){return true}if(c.readyState==t){b();re...
  function i (line 21) | function i(C){k||(k=Ext.query("style, link[rel=stylesheet]"));if(k.lengt...
  function y (line 21) | function y(C){c.removeEventListener(r,arguments.callee,false);i()}
  function b (line 21) | function b(C){if(!j){j=true;if(p){clearTimeout(p)}if(l){c.removeEventLis...
  function a (line 21) | function a(){z||(z=new Ext.util.Event());if(l){c.addEventListener(r,b,fa...
  function x (line 21) | function x(C,D){return function(){var E=Ext.toArray(arguments);if(D.targ...
  function w (line 21) | function w(D,E,C){return function(F){C.delay(E.buffer,D,null,[new Ext.Ev...
  function s (line 21) | function s(G,F,C,E,D){return function(H){Ext.EventManager.removeListener...
  function e (line 21) | function e(D,E,C){return function(G){var F=new Ext.util.DelayedTask(D);i...
  function h (line 21) | function h(H,G,C,J,K){var D=(!C||typeof C=="boolean")?{}:C,E=Ext.getDom(...
  function e (line 21) | function e(h){Ext.each(h,function(i){if(Ext.isArray(i)){e(i)}else{g.push...
  function g (line 21) | function g(m,p,n,q,l,j){m=Ext.getDom(m);var k;if(e.useDom){k=c(p,null);i...
  function c (line 21) | function c(j,r){var k,u=document,p,s,m,t;if(Ext.isArray(j)){k=u.createDo...
  function d (line 21) | function d(j,l,p,k){if(p&&a){if(p.substr(0,5)=="this."){return c.call(p....
  function fn (line 21) | function fn(m,name,format,args){if(format&&useF){args=args?","+args:"";i...
  function a (line 21) | function a(j){var i=(this.methodEvents=this.methodEvents||{})[j],d,c,g,h...
  function g (line 21) | function g(i){return function(){return h.fireEvent.apply(h,[i].concat(Ar...
  function c (line 21) | function c(g){g.stopPropagation();if(b){g.preventDefault()}}
  function a (line 21) | function a(h){var i=this;i.transaction=null;if(h.argument.form&&h.argume...
  function g (line 21) | function g(h,i,j){this.fireEvent(i||d,this.el,h);if(Ext.isFunction(h.arg...
  function e (line 21) | function e(h){g.call(this,h,c,!!(this.transaction=null))}
  function b (line 21) | function b(d){var c=Array.prototype.slice.call(arguments,1);return d.rep...
  function fn (line 21) | function fn(m,name,format,args,math){if(name.substr(0,4)=="xtpl"){return...
  function codeFn (line 21) | function codeFn(m,code){return"'"+sep+"("+code.replace(/\\'/g,"'")+")"+s...
  function g (line 21) | function g(h){try{this.execute(e,h,undefined,c)}catch(i){this.handleExce...
  function b (line 21) | function b(e,j){if(j){var h=a[e.toggleGroup];for(var d=0,c=h.length;d<c;...
  function g (line 21) | function g(){var l=location.href,m=l.indexOf("#"),n=m>=0?l.substr(m+1):n...
  function a (line 21) | function a(){c.value=d}
  function h (line 21) | function h(l){d=l;Ext.History.fireEvent("change",l)}
  function i (line 21) | function i(m){var l=['<html><body><div id="state">',Ext.util.Format.html...
  function b (line 21) | function b(){if(!e.contentWindow||!e.contentWindow.document){setTimeout(...
  function j (line 21) | function j(){d=c.value?c.value:g();if(Ext.isIE){b()}else{var l=g();setIn...
  function g (line 21) | function g(){if(K){return}try{var aa=k.getElementsByTagName("body")[0].a...
  function L (line 21) | function L(Y){if(K){Y()}else{V[V.length]=Y}}
  function t (line 21) | function t(Z){if(typeof P.addEventListener!=E){P.addEventListener("load"...
  function i (line 21) | function i(){if(U){W()}else{I()}}
  function W (line 21) | function W(){var Y=k.getElementsByTagName("body")[0];var ab=D(s);ab.setA...
  function I (line 21) | function I(){var ah=p.length;if(ah>0){for(var ag=0;ag<ah;ag++){var Z=p[a...
  function A (line 21) | function A(ab){var Y=null;var Z=c(ab);if(Z&&Z.nodeName=="OBJECT"){if(typ...
  function B (line 21) | function B(){return !a&&G("6.0.65")&&(N.win||N.mac)&&!(N.wk&&N.wk<312)}
  function Q (line 21) | function Q(ab,ac,Y,aa){a=true;F=aa||null;C={success:false,id:Y};var af=c...
  function q (line 21) | function q(Z){if(N.ie&&N.win&&Z.readyState!=4){var Y=D("div");Z.parentNo...
  function h (line 21) | function h(ad){var ab=D("div");if(N.win&&N.ie){ab.innerHTML=ad.innerHTML...
  function v (line 21) | function v(aj,ah,Z){var Y,ab=c(Z);if(N.wk&&N.wk<312){return Y}if(ab){if(...
  function e (line 21) | function e(aa,Y,Z){var ab=D("param");ab.setAttribute("name",Y);ab.setAtt...
  function z (line 21) | function z(Z){var Y=c(Z);if(Y&&Y.nodeName=="OBJECT"){if(N.ie&&N.win){Y.s...
  function b (line 21) | function b(aa){var Z=c(aa);if(Z){for(var Y in Z){if(typeof Z[Y]=="functi...
  function c (line 21) | function c(aa){var Y=null;try{Y=k.getElementById(aa)}catch(Z){}return Y}
  function D (line 21) | function D(Y){return k.createElement(Y)}
  function j (line 21) | function j(aa,Y,Z){aa.attachEvent(Y,Z);J[J.length]=[aa,Y,Z]}
  function G (line 21) | function G(aa){var Z=N.pv,Y=aa.split(".");Y[0]=parseInt(Y[0],10);Y[1]=pa...
  function w (line 21) | function w(ad,Z,ae,ac){if(N.ie&&N.mac){return}var ab=k.getElementsByTagN...
  function x (line 21) | function x(aa,Y){if(!n){return}var Z=Y?"visible":"hidden";if(K&&c(aa)){c...
  function M (line 21) | function M(Z){var aa=/[\\\"<>\.;]/;var Y=aa.exec(Z)!=null;return Y&&type...
  function a (line 21) | function a(d,c){if(!c.tryActivate(c.items.indexOf(c.activeItem)-1,-1)){c...
  function b (line 21) | function b(d,c){if(!c.tryActivate(c.items.indexOf(c.activeItem)+1,1)){c....
  function n (line 21) | function n(){h={};e=new Ext.util.MixedCollection();b=Ext.getDoc().addKey...
  function j (line 21) | function j(){if(e&&e.length>0){var o=e.clone();o.each(function(p){p.hide...
  function g (line 21) | function g(o){e.remove(o);if(e.length<1){b.disable();Ext.getDoc().un("mo...
  function k (line 21) | function k(o){var p=e.last();l=new Date();e.add(o);if(!a){b.enable();Ext...
  function c (line 21) | function c(o){if(o.activeChild){o.activeChild.hide()}if(o.autoHideTimer)...
  function i (line 21) | function i(o){var p=o.parentMenu;if(!p&&!o.allowOtherMenus){j()}else{if(...
  function m (line 21) | function m(o){if(l.getElapsed()>50&&e.length>0&&!o.getTarget(".x-menu"))...
  function d (line 21) | function d(j,h,i){return{itemId:j,cls:"x-btn-icon",iconCls:"x-edit-"+j,e...

FILE: client/src/ext/ux/DataView-more.js
  function fillRegions (line 97) | function fillRegions(){
  function cancelClick (line 105) | function cancelClick(){
  function onBeforeStart (line 109) | function onBeforeStart(e){
  function onStart (line 113) | function onStart(e){
  function onDrag (line 127) | function onDrag(e){
  function onEnd (line 156) | function onEnd(e){
  function onRender (line 165) | function onRender(view){

FILE: client/src/ext/ux/FieldLabeler.js
  function getParentProperty (line 41) | function getParentProperty(propName) {

FILE: client/src/ext/ux/ux-all-debug.js
  function fillRegions (line 1031) | function fillRegions(){
  function cancelClick (line 1039) | function cancelClick(){
  function onBeforeStart (line 1043) | function onBeforeStart(e){
  function onStart (line 1047) | function onStart(e){
  function onDrag (line 1061) | function onDrag(e){
  function onEnd (line 1090) | function onEnd(e){
  function onRender (line 1099) | function onRender(view){

FILE: client/src/ext/ux/ux-all.js
  function n (line 21) | function n(){d=[];j.all.each(function(q){d[d.length]=q.getRegion()});k=j...
  function e (line 21) | function e(){return false}
  function g (line 21) | function g(q){return !b||q.target==j.el.dom}
  function o (line 21) | function o(q){j.on("containerclick",e,j,{single:true});if(!h){h=j.el.cre...
  function c (line 21) | function c(z){var A=l.startXY;var E=l.getXY();var C=Math.min(A[0],E[0]);...
  function a (line 21) | function a(q){if(!Ext.isIE){j.un("containerclick",e,j)}if(h){h.setDispla...
  function p (line 21) | function p(q){l=new Ext.dd.DragTracker({onBeforeStart:g,onStart:o,onDrag...

FILE: client/src/js/FileSaver.js
  function bom (line 29) | function bom(blob, opts) {
  function download (line 49) | function download(url, name, opts) {
  function corsEnabled (line 65) | function corsEnabled(url) {
  function click (line 78) | function click(node) {

FILE: client/src/js/SM/Acl.js
  function renderResource (line 337) | function renderResource (value, metadata, record) {
  function handleTreeClick (line 490) | function handleTreeClick (node) {
  function handleAddBtnItem (line 507) | function handleAddBtnItem(item) {
  function makeAssignment (line 512) | function makeAssignment(selectedNode, access) {
  function isTreeNodeInRulesGrid (line 534) | function isTreeNodeInRulesGrid(node) {
  function onSave (line 602) | async function onSave () {

FILE: client/src/js/SM/ActivityHandler.js
  class ActivityHandler (line 1) | class ActivityHandler {
    method add (line 12) | add() {
    method remove (line 22) | remove() {
    method throttledActiveMessage (line 32) | throttledActiveMessage() {

FILE: client/src/js/SM/Ajax.js
  function setHeader (line 7) | function setHeader(o) {
  function createExceptionObject (line 26) | function createExceptionObject(tId, callbackArg, isAbort, isTimeout) {
  function initHeader (line 38) | function initHeader(label, value) {
  function createResponseObject (line 43) | function createResponseObject(o, callbackArg) {
  function releaseObject (line 80) | function releaseObject(o) {
  function handleTransactionResponse (line 89) | function handleTransactionResponse(o, callback, isAbort, isTimeout) {
  function checkResponse (line 155) | function checkResponse(o, callback, conn, tId, poll, cbTimeout){
  function checkTimeout (line 168) | function checkTimeout(o, callback){
  function handleReadyState (line 174) | function handleReadyState(o, callback){
  function asyncRequest (line 189) | function asyncRequest(method, uri, callback, postData) {
  function getConnectionObject (line 216) | function getConnectionObject() {
  function createXhrObject (line 230) | function createXhrObject(transactionId) {

FILE: client/src/js/SM/AppData.js
  class JSONLObjectStream (line 204) | class JSONLObjectStream extends TransformStream {
    method constructor (line 205) | constructor (separator = '\n') {
  class FileReaderProgressStream (line 262) | class FileReaderProgressStream extends TransformStream {
    method constructor (line 263) | constructor (fileSize, progressFn) {
  function btnHandler (line 299) | function btnHandler (btn) {
  function analyze (line 303) | async function analyze (fileObj) {
  function upload (line 371) | async function upload (fileObj) {
  function onFileSelected (line 417) | async function onFileSelected (uploadField) {

FILE: client/src/js/SM/AppInfo.js
  function transformV1_0 (line 46) | function transformV1_0(input) {
  function transformV0_0 (line 93) | function transformV0_0(input) {
  function loadData (line 382) | function loadData(o) {
  function loadData (line 409) | function loadData(data) {
  function renderTree (line 417) | function renderTree() {
  function loadData (line 1750) | function loadData(data) {
  function loadGrants (line 1779) | function loadGrants(sm, index, record) {
  function syncGridsOnRowSelect (line 1794) | function syncGridsOnRowSelect(sm, rowIndex, e) {
  function loadData (line 2027) | function loadData(data) {
  function getTotalLengths (line 2041) | function getTotalLengths(tables) {
  function formatBytes (line 2053) | function formatBytes(bytes, decimals = 2) {
  function onRowSelect (line 2522) | function onRowSelect(sm, index, record) {
  function loadData (line 2563) | function loadData(data) {
  function loadData (line 2758) | function loadData(data) {
  function loadData (line 2998) | function loadData(data) {
  function loadData (line 3032) | function loadData(data) {
  function loadData (line 3139) | function loadData(data) {
  function loadData (line 3259) | function loadData(data) {
  function getValues (line 3307) | function getValues() {
  function loadData (line 3387) | function loadData({ data, source }) {
  function obfuscateClients (line 3520) | function obfuscateClients(operationIds) {
  function onFileSelected (line 3561) | async function onFileSelected(uploadField) {
  function onFetchFromApi (line 3584) | async function onFetchFromApi(includeRowCounts = false) {
  function onSaveFull (line 3599) | function onSaveFull() {
  function onSaveShared (line 3606) | function onSaveShared(options) {
  function downloadBlob (line 3614) | function downloadBlob(blob, filename) {

FILE: client/src/js/SM/AssetSelection.js
  function setupDragZone (line 165) | function setupDragZone (grid) {
  function handleSelections (line 277) | function handleSelections() {
  function initPanel (line 291) | async function initPanel({ benchmarkId, labelId }) {
  function changeSelectedAssets (line 334) | function changeSelectedAssets(srcGrid, records, dstGrid) {
  function getValue (line 364) | function getValue() {

FILE: client/src/js/SM/Attachments.js
  function readBinaryStringAsync (line 322) | function readBinaryStringAsync(file) {
  function readArrayBufferAsync (line 333) | function readArrayBufferAsync(file) {

FILE: client/src/js/SM/Classification.js
  class Classification (line 5) | class Classification {
    method constructor (line 6) | constructor (apiClassification) {

FILE: client/src/js/SM/CollectionClone.js
  function getApiValues (line 158) | function getApiValues() {
  function handleInput (line 171) | function handleInput () {
  function NDJSONStream (line 286) | function NDJSONStream(separator = '\n') {
  function clickThruHandler (line 314) | function clickThruHandler () {
  function cloneBtnHandler (line 320) | async function cloneBtnHandler (btn) {
  function vpResize (line 436) | function vpResize (vp, adjWidth, adjHeight) {

FILE: client/src/js/SM/CollectionPanel.js
  function renderWithToolbar (line 250) | function renderWithToolbar(v, md) {
  function renderWithToolbar (line 575) | function renderWithToolbar(v) {
  function cellclick (line 700) | function cellclick(grid, rowIndex, columnIndex, e) {
  method afterrender (line 787) | afterrender(me) {
  function getUnreviewedOrOpen (line 1298) | function getUnreviewedOrOpen(sev) {
  function onRowSelect (line 1489) | async function onRowSelect(cm, index, record) {
  function onRowSelect (line 1589) | async function onRowSelect(cm, index, record) {
  function onRowSelectLabel (line 1702) | async function onRowSelectLabel(cm, index, record) {
  function onRowSelectAsset (line 1714) | async function onRowSelectAsset(cm, index, record) {
  function loadAggAssetGrid (line 1720) | async function loadAggAssetGrid(params) {
  function setCurrentBaseParams (line 2054) | function setCurrentBaseParams(labelIds) {
  function updateFilterableLabels (line 2071) | async function updateFilterableLabels() {
  function updateOverviewTitle (line 2096) | function updateOverviewTitle() {
  function reloadBtnHandler (line 2103) | function reloadBtnHandler() { updateData({event: 'reload'}) }
  function onLabelFilter (line 2106) | async function onLabelFilter(srcCollectionId, srcLabelIds) {
  function updateData (line 2130) | async function updateData({event} = {}) {
  function cancelTimers (line 2173) | function cancelTimers() {
  function calcRefreshDelay (line 2181) | function calcRefreshDelay(maxTouchTs) {

FILE: client/src/js/SM/ColumnFilters.js
  function getValue (line 539) | function getValue () {
  function getValue (line 639) | function getValue() {
  function isAllSelected (line 645) | function isAllSelected () {
  function getValue (line 738) | function getValue () {
  function setValue (line 747) | function setValue(value) {
  function loadData (line 778) | function loadData (data, value) {
  function setGridSizeForXY (line 792) | function setGridSizeForXY(xy) {
  function sortGrid (line 809) | function sortGrid() {
  function prepareForShow (line 820) | function prepareForShow() {

FILE: client/src/js/SM/Error.js
  class SmError (line 3) | class SmError extends Error {
    method constructor (line 4) | constructor(message) {
  class PrivilegeError (line 10) | class PrivilegeError extends SmError {
    method constructor (line 11) | constructor(detail) {
  class ExtRequestError (line 17) | class ExtRequestError extends SmError {
    method constructor (line 18) | constructor(detail, message = 'Ext.Ajax.request() failed') {
  class ExtDataProxyError (line 37) | class ExtDataProxyError extends SmError {
    method constructor (line 38) | constructor(exception, message = 'Ext.data.DataProxy fired an exceptio...
  class NonJsonResponse (line 65) | class NonJsonResponse extends ExtRequestError {
    method constructor (line 66) | constructor(detail) {

FILE: client/src/js/SM/Exports.js
  function checkStateHandler (line 580) | function checkStateHandler() {
  function navTreeClick (line 594) | function navTreeClick(node, e) {
  function getInitialOptions (line 671) | function getInitialOptions (dstCollectionData) {
  function saveOptions (line 688) | function saveOptions() {
  function formatBytes (line 706) | function formatBytes(a, b = 2, k = 1024) {

FILE: client/src/js/SM/FindingsPanel.js
  function getStatSprites (line 235) | function getStatSprites (store) {
  function engineResultConverter (line 365) | function engineResultConverter (v,r) {
  function getStatSprites (line 416) | function getStatSprites (store) {
  function downloadBlob (line 831) | function downloadBlob(blob, filename) {
  function onChildRowDblClick (line 890) | function onChildRowDblClick (grid, rowIndex) {
  function genPoamBtnHandler (line 907) | function genPoamBtnHandler() {

FILE: client/src/js/SM/Global.js
  function tagValueProcessor (line 225) | function tagValueProcessor(tagName, tagValue) {

FILE: client/src/js/SM/Grant.js
  function shouldHideNode (line 49) | function shouldHideNode ({text, lastAccess}) {
  function filterNodes (line 58) | function filterNodes (node) {
  function viewready (line 382) | function viewready (grid) {
  function getValue (line 396) | function getValue () {
  function setValue (line 412) | function setValue (v) {
  function handleTreeCheck (line 469) | function handleTreeCheck(node) {
  function handleAddBtnItem (line 505) | function handleAddBtnItem (menuItem) {
  function saveHandler (line 635) | async function saveHandler () {
  function grantGridStoreHandler (line 660) | function grantGridStoreHandler () {
  function handleTreeCheck (line 717) | function handleTreeCheck(node) {
  function onInitialExpandNode (line 724) | function onInitialExpandNode(node) {
  function saveHandler (line 751) | function saveHandler () {

FILE: client/src/js/SM/Inventory.js
  function getFieldOptions (line 117) | function getFieldOptions() {
  function handleCheckboxes (line 121) | function handleCheckboxes() {
  function getFieldOptions (line 231) | function getFieldOptions() {
  function handleCheckboxes (line 235) | function handleCheckboxes() {
  function getFieldOptions (line 277) | function getFieldOptions() {
  function fetchApiDataAsText (line 387) | async function fetchApiDataAsText(groupBy, includeProjection, baseParams...
  function exportHandler (line 409) | async function exportHandler() {
  function updateDisplay (line 442) | function updateDisplay() {
  function getState (line 468) | function getState() {
  function setState (line 493) | function setState() {

FILE: client/src/js/SM/Job.js
  function dateRenderWithToolbar (line 250) | function dateRenderWithToolbar(v, md) {
  function rowmousedown (line 260) | function rowmousedown(grid, rowIndex, e) {
  function setupDragZone (line 815) | function setupDragZone(grid) {
  function handleSelections (line 995) | function handleSelections() {
  function initPanel (line 1009) | async function initPanel(apiJob) {
  function fireSelectedChanged (line 1028) | function fireSelectedChanged() {
  function changeSelected (line 1032) | function changeSelected(srcGrid, records, dstGrid) {
  function getValue (line 1055) | function getValue() {
  function runNowFn (line 1365) | async function runNowFn() {
  function loadRuns (line 1399) | async function loadRuns(jobId) {
  function onJobChanged (line 1410) | function onJobChanged() {

FILE: client/src/js/SM/Library.js
  function getStig (line 231) | async function getStig(benchmarkId, revisionStr) {
  function disableRevisionComboBoxes (line 370) | function disableRevisionComboBoxes(disable) {

FILE: client/src/js/SM/LogStream.js
  function isAtBottom (line 160) | function isAtBottom() {
  function getValues (line 490) | function getValues() {
  function getValues (line 525) | function getValues() {
  function getValue (line 579) | function getValue() {
  function openHandler (line 613) | function openHandler(event) {
  function errorHandler (line 621) | function errorHandler(event) {
  function mainMessageHandler (line 752) | async function mainMessageHandler(event) {
  function authorizeWebSocket (line 777) | async function authorizeWebSocket() {
  function tokenBroadcastHandler (line 814) | function tokenBroadcastHandler(event) {
  function closeHandler (line 824) | function closeHandler(event) {
  function retryHandler (line 840) | function retryHandler(attempt) {

FILE: client/src/js/SM/Manage.js
  function onSelect (line 157) | function onSelect(item, record, index) {
  function onStatusCheck (line 362) | function onStatusCheck(item, checked) {
  function onComboSelect (line 367) | function onComboSelect(item, record, index) {
  function onComboSelect (line 441) | function onComboSelect(item, record, index) {
  function showEditGrant (line 765) | function showEditGrant (grantData, record) {
  function editAcl (line 781) | function editAcl (grantData) {
  function removeGrant (line 784) | function removeGrant (grantData, record) {
  function cellclick (line 804) | function cellclick(grid, rowIndex, columnIndex, e) {
  function viewready (line 871) | function viewready (grid) {
  function setValue (line 886) | function setValue (v, append = false) {
  function getValue (line 890) | function getValue () {
  function cellclick (line 1019) | function cellclick(grid, rowIndex, columnIndex, e) {
  function grantChangeHandler (line 1411) | function grantChangeHandler (grantId, data) {
  function grantRemoveHandler (line 1419) | function grantRemoveHandler (data) {
  function onGrantDeleted (line 1426) | function onGrantDeleted ({collectionId, grantId}) {
  function onGrantUpdated (line 1432) | function onGrantUpdated({collectionId, api}) {
  function setFieldValues (line 1442) | function setFieldValues (apiCollection) {
  function getFieldValues (line 1527) | function getFieldValues () {
  function apiPatchSettings (line 1586) | async function apiPatchSettings(value) {
  function updateSettings (line 1599) | async function updateSettings() {
  function onGrantDeleted (line 1801) | function onGrantDeleted ({collectionId, grantId}) {
  function onGrantUpdated (line 1807) | function onGrantUpdated({collectionId, api}) {
  function downloadCsv (line 3572) | function downloadCsv(content, collectionName) {
  function generateCsvFromAssets (line 3584) | function generateCsvFromAssets(assets) {
  function errorRenderer (line 3759) | function errorRenderer(value) {
  function createLabels (line 4001) | async function createLabels(labels) {
  function setupDragZone (line 4239) | function setupDragZone(grid) {
  function handleSelections (line 4351) | function handleSelections() {
  function initPanel (line 4365) | async function initPanel(apiAsset) {
  function fireSelectedChanged (line 4386) | function fireSelectedChanged () {
  function changeSelected (line 4390) | function changeSelected(srcGrid, records, dstGrid) {
  function getValue (line 4411) | function getValue() {
  function setButtonState (line 5256) | function setButtonState () {

FILE: client/src/js/SM/MetaPanel.js
  function cellclick (line 606) | function cellclick(grid, rowIndex, columnIndex, e) {
  function onRowSelectNorth (line 1201) | async function onRowSelectNorth(cm, index, record) {
  function onRowSelectCenter (line 1212) | async function onRowSelectCenter(cm, index, record) {
  function onRowSelectNorth (line 1357) | async function onRowSelectNorth(cm, index, record) {
  function onRowSelectCenter (line 1367) | async function onRowSelectCenter(cm, index, record) {
  function setCurrentBaseParams (line 1625) | function setCurrentBaseParams(collectionIds) {
  function updateFilterableCollections (line 1636) | async function updateFilterableCollections() {
  function updateOverviewTitle (line 1658) | function updateOverviewTitle() {
  function reloadBtnHandler (line 1665) | function reloadBtnHandler() { updateData({ event: 'reload' }) }
  function onCollectionFilter (line 1668) | async function onCollectionFilter(srcCollectionIds) {
  function updateData (line 1691) | async function updateData({ event } = {}) {
  function cancelTimers (line 1734) | function cancelTimers() {
  function calcRefreshDelay (line 1740) | function calcRefreshDelay(maxTouchTs) {

FILE: client/src/js/SM/NavTree.js
  function sortFn (line 116) | function sortFn (a, b) {
  function sortFn (line 145) | function sortFn (a, b) {

FILE: client/src/js/SM/Review.js
  function reviewChanged (line 331) | function reviewChanged () {
  function loadValues (line 344) | function loadValues (values) {
  function initLastSavedData (line 364) | function initLastSavedData () {
  function isReviewSubmittable (line 372) | function isReviewSubmittable () {
  function setReviewFormTips (line 388) | function setReviewFormTips () {
  function setReviewFormItemStates (line 401) | function setReviewFormItemStates () {

FILE: client/src/js/SM/ReviewsImport.js
  function onSelect (line 952) | function onSelect(item, record, index) {
  function handleDragover (line 1017) | function handleDragover(e) {
  function handleDragleave (line 1023) | function handleDragleave(e) {
  function onFileDropped (line 1030) | async function onFileDropped(e) {
  function onFileSelected (line 1128) | function onFileSelected(uploadField) {
  function handleDragover (line 1431) | function handleDragover(e) {
  function handleDragleave (line 1438) | function handleDragleave(e) {
  function showImportResultFiles (line 2078) | async function showImportResultFiles(collectionId, createObjects = true,...
  function showImportResultFile (line 2521) | async function showImportResultFile(params) {
  function getScapBenchmarkMap (line 2847) | async function getScapBenchmarkMap() {
  function readTextFileAsync (line 2856) | function readTextFileAsync(file) {

FILE: client/src/js/SM/StackTrace.js
  function parseChrome (line 30) | function parseChrome(line) {
  function parseWinjs (line 62) | function parseWinjs(line) {
  function parseGecko (line 79) | function parseGecko(line) {
  function parseJSC (line 106) | function parseJSC(line) {
  function parseNode (line 123) | function parseNode(line) {

FILE: client/src/js/SM/StigRevision.js
  function processZip (line 507) | async function processZip (f, clobber) {
  function forceCheckboxHandler (line 626) | function forceCheckboxHandler (cb, checked) {

FILE: client/src/js/SM/TransferAssets.js
  function setMenuItems (line 11) | function setMenuItems (menu) {

FILE: client/src/js/SM/User.js
  function cellclick (line 197) | function cellclick (grid, rowIndex, columnIndex, e) {
  function fireSelectedChanged (line 290) | function fireSelectedChanged () {
  function handleAddBtnItem (line 297) | function handleAddBtnItem (menuItem) {
  function changeSelected (line 307) | function changeSelected(srcGrid, records, dstGrid) {
  function handleSelections (line 352) | function handleSelections() {
  function initPanel (line 366) | async function initPanel(apiUserOrGroup) {
  function getValue (line 399) | function getValue() {
  function setupDragZone (line 543) | function setupDragZone(grid) {
  function handleSelections (line 652) | function handleSelections() {
  function fireSelectedChanged (line 666) | function fireSelectedChanged () {
  function initPanel (line 671) | async function initPanel(apiUser) {
  function changeSelected (line 697) | function changeSelected(srcGrid, records, dstGrid) {
  function getValue (line 728) | function getValue() {
  function onPropsUpdate (line 1323) | async function onPropsUpdate(property, value) {
  function onClientValidation (line 1341) | function onClientValidation(formPanel, isValid) {
  function windowBtnHandler (line 1345) | async function windowBtnHandler(btn) {
  function afterLoad (line 1635) | function afterLoad(store, records) {

FILE: client/src/js/SM/UserGroup.js
  function setupDragZone (line 353) | function setupDragZone(grid) {
  function handleSelections (line 465) | function handleSelections() {
  function initPanel (line 479) | async function initPanel(apiUserGroup) {
  function fireSelectedChanged (line 524) | function fireSelectedChanged () {
  function changeSelected (line 528) | function changeSelected(srcGrid, records, dstGrid) {
  function getValue (line 549) | function getValue() {
  function onPropsUpdate (line 689) | async function onPropsUpdate(property, value) {
  function onClientValidation (line 706) | function onClientValidation(formPanel, isValid) {
  function windowBtnHandler (line 710) | async function windowBtnHandler(btn) {

FILE: client/src/js/collectionAdmin.js
  function addCollectionAdmin (line 1) | function addCollectionAdmin( params ) {
  function showAdminCreatePanel (line 108) | async function showAdminCreatePanel() {

FILE: client/src/js/collectionManager.js
  function addCollectionManager (line 1) | async function addCollectionManager( params ) {

FILE: client/src/js/collectionReview.js
  function addCollectionReview (line 6) | async function addCollectionReview ( params ) {
  function renderOpen (line 2110) | function renderOpen(value, metaData, record, rowIndex, colIndex, store) {
  function renderCounts (line 2121) | function renderCounts(value, metaData, record, rowIndex, colIndex, store) {
  function renderStatusCounts (line 2128) | function renderStatusCounts(value, metaData, record, rowIndex, colIndex,...

FILE: client/src/js/completionStatus.js
  function addCompletionStatus (line 1) | function addCompletionStatus( params) {
  function renderGrey (line 281) | function renderGrey(value, metaData, record, rowIndex, colIndex, store) {
  function renderDays (line 285) | function renderDays(value, metaData, record, rowIndex, colIndex, store) {
  function renderCat1 (line 298) | function renderCat1(value, metaData, record, rowIndex, colIndex, store) {
  function renderCat23 (line 307) | function renderCat23(value, metaData, record, rowIndex, colIndex, store) {
  function renderUndone (line 316) | function renderUndone(value, metaData, record, rowIndex, colIndex, store) {
  function renderDone (line 324) | function renderDone(value, metaData, record, rowIndex, colIndex, store) {
  function renderChecklist (line 333) | function renderChecklist(value, metaData, record, rowIndex, colIndex, st...
  function renderAsset (line 338) | function renderAsset(value, metaData, record, rowIndex, colIndex, store) {

FILE: client/src/js/diff.js
  function Diff (line 7) | function Diff() {}
  function done (line 21) | function done(value) {
  function execEditLength (line 62) | function execEditLength() {
  function buildValues (line 206) | function buildValues(diff, components, newString, oldString, useLongestT...
  function clonePath (line 259) | function clonePath(path) {
  function diffChars (line 267) | function diffChars(oldStr, newStr, options) {
  function generateOptions (line 271) | function generateOptions(options, defaults) {
  function diffWords (line 333) | function diffWords(oldStr, newStr, options) {
  function diffWordsWithSpace (line 339) | function diffWordsWithSpace(oldStr, newStr, options) {
  function diffLines (line 371) | function diffLines(oldStr, newStr, callback) {
  function diffTrimmedLines (line 374) | function diffTrimmedLines(oldStr, newStr, callback) {
  function diffSentences (line 387) | function diffSentences(oldStr, newStr, callback) {
  function diffCss (line 397) | function diffCss(oldStr, newStr, callback) {
  function _typeof (line 401) | function _typeof(obj) {
  function _toConsumableArray (line 417) | function _toConsumableArray(arr) {
  function _arrayWithoutHoles (line 421) | function _arrayWithoutHoles(arr) {
  function _iterableToArray (line 425) | function _iterableToArray(iter) {
  function _unsupportedIterableToArray (line 429) | function _unsupportedIterableToArray(o, minLen) {
  function _arrayLikeToArray (line 438) | function _arrayLikeToArray(arr, len) {
  function _nonIterableSpread (line 446) | function _nonIterableSpread() {
  function diffJson (line 471) | function diffJson(oldObj, newObj, options) {
  function canonicalize (line 476) | function canonicalize(obj, stack, replacementStack, replacer, key) {
  function diffArrays (line 553) | function diffArrays(oldArr, newArr, callback) {
  function parsePatch (line 557) | function parsePatch(uniDiff) {
  function distanceIterator (line 715) | function distanceIterator (start, minLine, maxLine) {
  function applyPatch (line 756) | function applyPatch(source, uniDiff) {
  function applyPatches (line 891) | function applyPatches(uniDiff, options) {
  function structuredPatch (line 924) | function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHe...
  function formatPatch (line 1055) | function formatPatch(diff) {
  function createTwoFilesPatch (line 1088) | function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, o...
  function createPatch (line 1091) | function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, opt...
  function arrayEqual (line 1095) | function arrayEqual(a, b) {
  function arrayStartsWith (line 1102) | function arrayStartsWith(array, start) {
  function calcLineCount (line 1116) | function calcLineCount(hunk) {
  function merge (line 1133) | function merge(mine, theirs, base) {
  function loadPatch (line 1209) | function loadPatch(param, base) {
  function fileNameChanged (line 1225) | function fileNameChanged(patch) {
  function selectField (line 1229) | function selectField(index, mine, theirs) {
  function hunkBefore (line 1241) | function hunkBefore(test, check) {
  function cloneHunk (line 1245) | function cloneHunk(hunk, offset) {
  function mergeLines (line 1255) | function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) {
  function mutualChange (line 1312) | function mutualChange(hunk, mine, their) {
  function removal (line 1342) | function removal(hunk, mine, their, swap) {
  function conflict (line 1355) | function conflict(hunk, mine, their) {
  function insertLeading (line 1364) | function insertLeading(hunk, insert, their) {
  function insertTrailing (line 1372) | function insertTrailing(hunk, insert) {
  function collectChange (line 1379) | function collectChange(state) {
  function collectContext (line 1401) | function collectContext(state, matchChanges) {
  function allRemoves (line 1456) | function allRemoves(changes) {
  function skipRemoveSuperset (line 1462) | function skipRemoveSuperset(state, removeChanges, delta) {
  function calcOldNewLineCount (line 1475) | function calcOldNewLineCount(lines) {
  function convertChangesToDMP (line 1515) | function convertChangesToDMP(changes) {
  function convertChangesToXML (line 1537) | function convertChangesToXML(changes) {
  function escapeHTML (line 1561) | function escapeHTML(s) {

FILE: client/src/js/findingsSummary.js
  function addFindingsSummary (line 5) | function addFindingsSummary( params ) {

FILE: client/src/js/init.js
  function bootstrap (line 35) | async function bootstrap() {
  function getOidcMetadata (line 71) | async function getOidcMetadata() {
  function initializeOidcWorker (line 85) | async function initializeOidcWorker(redirectUri) {
  function extractParamString (line 97) | function extractParamString(url) {
  function processRedirectParams (line 103) | function processRedirectParams (paramStr) {
  function handleNoParameters (line 112) | async function handleNoParameters() {
  function handleRedirectAndParameters (line 126) | async function handleRedirectAndParameters(redirectUri, paramStr) {
  function appendStatus (line 165) | function appendStatus(html) {
  function setStatus (line 169) | function setStatus(html) {
  function escapeHtml (line 173) | function escapeHtml(str) {
  function appendError (line 177) | function appendError(message, showReauth = true) {
  function loadResources (line 189) | async function loadResources() {
  function setupOidcWorker (line 215) | async function setupOidcWorker() {
  function setupStateWorker (line 252) | async function setupStateWorker() {
  function hideSpinner (line 330) | function hideSpinner() {

FILE: client/src/js/jsonview.bundle.js
  function _typeof (line 4) | function _typeof(obj) {
  function expandedTemplate (line 20) | function expandedTemplate() {
  function notExpandedTemplate (line 27) | function notExpandedTemplate() {
  function hideNodeChildren (line 35) | function hideNodeChildren(node) {
  function showNodeChildren (line 45) | function showNodeChildren(node) {
  function setCaretIconDown (line 55) | function setCaretIconDown(node) {
  function setCaretIconRight (line 65) | function setCaretIconRight(node) {
  function toggleNode (line 75) | function toggleNode(node) {
  function createContainerElement (line 87) | function createContainerElement() {
  function createNodeElement (line 93) | function createNodeElement(node) {
  function getDataType (line 130) | function getDataType(val) {
  function traverseTree (line 139) | function traverseTree(node, callback) {
  function createNode (line 149) | function createNode() {
  function createSubnode (line 163) | function createSubnode(data, node) {
  function createTree (line 179) | function createTree(jsonData) {
  function renderJSON (line 190) | function renderJSON(jsonData, targetElement) {
  function render (line 197) | function render(tree, targetElement) {
  function expandChildren (line 209) | function expandChildren(node) {
  function collapseChildren (line 217) | function collapseChildren(node) {

FILE: client/src/js/library.js
  function addLibraryStig (line 1) | async function addLibraryStig( params ) {

FILE: client/src/js/modules/source-map/source-map.js
  function t (line 1) | function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{...
    method constructor (line 1) | constructor(){this._array=[],this._set=new Map}
    method fromArray (line 1) | static fromArray(e,n){const r=new t;for(let t=0,o=e.length;t<o;t++)r.a...
    method size (line 1) | size(){return this._set.size}
    method add (line 1) | add(e,n){const t=this.has(e),r=this._array.length;t&&!n||this._array.p...
    method has (line 1) | has(e){return this._set.has(e)}
    method indexOf (line 1) | indexOf(e){const n=this._set.get(e);if(n>=0)return n;throw new Error('...
    method at (line 1) | at(e){if(e>=0&&e<this._array.length)return this._array[e];throw new Er...
    method toArray (line 1) | toArray(){return this._array.slice()}
  function o (line 1) | function o(e){const n=e.match(t);return n?{scheme:n[1],auth:n[2],host:n[...
  function i (line 1) | function i(e){let n="";return e.scheme&&(n+=e.scheme+":"),n+="//",e.auth...
  function l (line 1) | function l(e,n){""===e&&(e="."),""===n&&(n=".");const t=o(n),l=o(e);if(l...
    method constructor (line 1) | constructor(e){e||(e={}),this._file=o.getArg(e,"file",null),this._sour...
    method fromSourceMap (line 1) | static fromSourceMap(e){const n=e.sourceRoot,t=new l({file:e.file,sour...
    method addMapping (line 1) | addMapping(e){const n=o.getArg(e,"generated"),t=o.getArg(e,"original",...
    method setSourceContent (line 1) | setSourceContent(e,n){let t=e;null!=this._sourceRoot&&(t=o.relative(th...
    method applySourceMap (line 1) | applySourceMap(e,n,t){let r=n;if(null==n){if(null==e.file)throw new Er...
    method _validateMapping (line 1) | _validateMapping(e,n,t,r){if(n&&"number"!=typeof n.line&&"number"!=typ...
    method _serializeMappings (line 1) | _serializeMappings(){let e,n,t,i,s=0,l=1,a=0,u=0,c=0,g=0,p="";const h=...
    method _generateSourcesContent (line 1) | _generateSourcesContent(e,n){return e.map((function(e){if(!this._sourc...
    method toJSON (line 1) | toJSON(){const e={version:this._version,sources:this._sources.toArray(...
    method toString (line 1) | toString(){return JSON.stringify(this.toJSON())}
    method constructor (line 1) | constructor(e,n,t,r,o){this.children=[],this.sourceContents={},this.li...
    method fromStringWithSourceMap (line 1) | static fromStringWithSourceMap(e,n,t){const r=new l,s=e.split(i);let a...
    method add (line 1) | add(e){if(Array.isArray(e))e.forEach((function(e){this.add(e)}),this);...
    method prepend (line 1) | prepend(e){if(Array.isArray(e))for(let n=e.length-1;n>=0;n--)this.prep...
    method walk (line 1) | walk(e){let n;for(let t=0,r=this.children.length;t<r;t++)n=this.childr...
    method join (line 1) | join(e){let n,t;const r=this.children.length;if(r>0){for(n=[],t=0;t<r-...
    method replaceRight (line 1) | replaceRight(e,n){const t=this.children[this.children.length-1];return...
    method setSourceContent (line 1) | setSourceContent(e,n){this.sourceContents[o.toSetString(e)]=n}
    method walkSourceContents (line 1) | walkSourceContents(e){for(let n=0,t=this.children.length;n<t;n++)this....
    method toString (line 1) | toString(){let e="";return this.walk((function(n){e+=n})),e}
    method toStringWithSourceMap (line 1) | toStringWithSourceMap(e){const n={code:"",line:1,column:0},t=new r(e);...
  function u (line 1) | function u(e){return e}
    method constructor (line 1) | constructor(e,n){return e==a?Promise.resolve(this):function(e,n){let t...
    method initialize (line 1) | static initialize(e){s.initialize(e["lib/mappings.wasm"])}
    method fromSourceMap (line 1) | static fromSourceMap(e,n){return function(e,n){return c.fromSourceMap(...
    method with (line 1) | static async with(e,n,t){const r=await new u(e,n);try{return await t(r...
    method _parseMappings (line 1) | _parseMappings(e,n){throw new Error("Subclasses must implement _parseM...
    method eachMapping (line 1) | eachMapping(e,n,t){throw new Error("Subclasses must implement eachMapp...
    method allGeneratedPositionsFor (line 1) | allGeneratedPositionsFor(e){throw new Error("Subclasses must implement...
    method destroy (line 1) | destroy(){throw new Error("Subclasses must implement destroy")}
  function c (line 1) | function c(e){if(!e)return!1;const n=e.length;if(n<9)return!1;if(95!==e....
    method constructor (line 1) | constructor(e,n){return super(a).then(t=>{let o=e;"string"==typeof e&&...
    method _findSourceIndex (line 1) | _findSourceIndex(e){let n=e;if(null!=this.sourceRoot&&(n=r.relative(th...
    method fromSourceMap (line 1) | static fromSourceMap(e,n){return new c(e.toString())}
    method sources (line 1) | get sources(){return this._absoluteSources.slice()}
    method _getMappingsPtr (line 1) | _getMappingsPtr(){return 0===this._mappingsPtr&&this._parseMappings(th...
    method _parseMappings (line 1) | _parseMappings(e,n){const t=e.length,r=this._wasm.exports.allocate_map...
    method eachMapping (line 1) | eachMapping(e,n,t){const o=n||null,i=t||u.GENERATED_ORDER,s=this.sourc...
    method allGeneratedPositionsFor (line 1) | allGeneratedPositionsFor(e){let n=r.getArg(e,"source");const t=r.getAr...
    method destroy (line 1) | destroy(){0!==this._mappingsPtr&&(this._wasm.exports.free_mappings(thi...
    method computeColumnSpans (line 1) | computeColumnSpans(){this._computedColumnSpans||(this._wasm.exports.co...
    method originalPositionFor (line 1) | originalPositionFor(e){const n={generatedLine:r.getArg(e,"line"),gener...
    method hasContentsOfAllSources (line 1) | hasContentsOfAllSources(){return!!this.sourcesContent&&(this.sourcesCo...
    method sourceContentFor (line 1) | sourceContentFor(e,n){if(!this.sourcesContent)return null;const t=this...
    method generatedPositionFor (line 1) | generatedPositionFor(e){let n=r.getArg(e,"source");if(n=this._findSour...
  function g (line 1) | function g(e,n){return e===n?0:null===e?1:null===n?-1:e>n?1:-1}
    method constructor (line 1) | constructor(e,n){return super(a).then(t=>{let o=e;"string"==typeof e&&...
    method _generatedMappings (line 1) | get _generatedMappings(){return this.__generatedMappings||this._sortGe...
    method _originalMappings (line 1) | get _originalMappings(){return this.__originalMappings||this._sortOrig...
    method _generatedMappingsUnsorted (line 1) | get _generatedMappingsUnsorted(){return this.__generatedMappingsUnsort...
    method _originalMappingsUnsorted (line 1) | get _originalMappingsUnsorted(){return this.__originalMappingsUnsorted...
    method _sortGeneratedMappings (line 1) | _sortGeneratedMappings(){const e=this._generatedMappingsUnsorted;e.sor...
    method _sortOriginalMappings (line 1) | _sortOriginalMappings(){const e=this._originalMappingsUnsorted;e.sort(...
    method sources (line 1) | get sources(){const e=[];for(let n=0;n<this._sections.length;n++)for(l...
    method originalPositionFor (line 1) | originalPositionFor(e){const n={generatedLine:r.getArg(e,"line"),gener...
    method hasContentsOfAllSources (line 1) | hasContentsOfAllSources(){return this._sections.every((function(e){ret...
    method sourceContentFor (line 1) | sourceContentFor(e,n){for(let n=0;n<this._sections.length;n++){const t...
    method generatedPositionFor (line 1) | generatedPositionFor(e){for(let n=0;n<this._sections.length;n++){const...
    method _parseMappings (line 1) | _parseMappings(e,n){const t=this.__generatedMappingsUnsorted=[],o=this...
    method eachMapping (line 1) | eachMapping(e,n,t){const o=n||null;let i;switch(t||u.GENERATED_ORDER){...
    method _findMapping (line 1) | _findMapping(e,n,t,r,i,s){if(e[t]<=0)throw new TypeError("Line must be...
    method allGeneratedPositionsFor (line 1) | allGeneratedPositionsFor(e){const n=r.getArg(e,"line"),t={source:r.get...
    method destroy (line 1) | destroy(){for(let e=0;e<this._sections.length;e++)this._sections[e].co...
  class l (line 1) | class l{constructor(e){e||(e={}),this._file=o.getArg(e,"file",null),this...
    method constructor (line 1) | constructor(e){e||(e={}),this._file=o.getArg(e,"file",null),this._sour...
    method fromSourceMap (line 1) | static fromSourceMap(e){const n=e.sourceRoot,t=new l({file:e.file,sour...
    method addMapping (line 1) | addMapping(e){const n=o.getArg(e,"generated"),t=o.getArg(e,"original",...
    method setSourceContent (line 1) | setSourceContent(e,n){let t=e;null!=this._sourceRoot&&(t=o.relative(th...
    method applySourceMap (line 1) | applySourceMap(e,n,t){let r=n;if(null==n){if(null==e.file)throw new Er...
    method _validateMapping (line 1) | _validateMapping(e,n,t,r){if(n&&"number"!=typeof n.line&&"number"!=typ...
    method _serializeMappings (line 1) | _serializeMappings(){let e,n,t,i,s=0,l=1,a=0,u=0,c=0,g=0,p="";const h=...
    method _generateSourcesContent (line 1) | _generateSourcesContent(e,n){return e.map((function(e){if(!this._sourc...
    method toJSON (line 1) | toJSON(){const e={version:this._version,sources:this._sources.toArray(...
    method toString (line 1) | toString(){return JSON.stringify(this.toJSON())}
    method constructor (line 1) | constructor(e,n,t,r,o){this.children=[],this.sourceContents={},this.li...
    method fromStringWithSourceMap (line 1) | static fromStringWithSourceMap(e,n,t){const r=new l,s=e.split(i);let a...
    method add (line 1) | add(e){if(Array.isArray(e))e.forEach((function(e){this.add(e)}),this);...
    method prepend (line 1) | prepend(e){if(Array.isArray(e))for(let n=e.length-1;n>=0;n--)this.prep...
    method walk (line 1) | walk(e){let n;for(let t=0,r=this.children.length;t<r;t++)n=this.childr...
    method join (line 1) | join(e){let n,t;const r=this.children.length;if(r>0){for(n=[],t=0;t<r-...
    method replaceRight (line 1) | replaceRight(e,n){const t=this.children[this.children.length-1];return...
    method setSourceContent (line 1) | setSourceContent(e,n){this.sourceContents[o.toSetString(e)]=n}
    method walkSourceContents (line 1) | walkSourceContents(e){for(let n=0,t=this.children.length;n<t;n++)this....
    method toString (line 1) | toString(){let e="";return this.walk((function(n){e+=n})),e}
    method toStringWithSourceMap (line 1) | toStringWithSourceMap(e){const n={code:"",line:1,column:0},t=new r(e);...
  class t (line 1) | class t{constructor(){this._array=[],this._set=new Map}static fromArray(...
    method constructor (line 1) | constructor(){this._array=[],this._set=new Map}
    method fromArray (line 1) | static fromArray(e,n){const r=new t;for(let t=0,o=e.length;t<o;t++)r.a...
    method size (line 1) | size(){return this._set.size}
    method add (line 1) | add(e,n){const t=this.has(e),r=this._array.length;t&&!n||this._array.p...
    method has (line 1) | has(e){return this._set.has(e)}
    method indexOf (line 1) | indexOf(e){const n=this._set.get(e);if(n>=0)return n;throw new Error('...
    method at (line 1) | at(e){if(e>=0&&e<this._array.length)return this._array[e];throw new Er...
    method toArray (line 1) | toArray(){return this._array.slice()}
  method constructor (line 1) | constructor(){this._array=[],this._sorted=!0,this._last={generatedLine:-...
  method unsortedForEach (line 1) | unsortedForEach(e,n){this._array.forEach(e,n)}
  method add (line 1) | add(e){!function(e,n){const t=e.generatedLine,o=n.generatedLine,i=e.gene...
  method toArray (line 1) | toArray(){return this._sorted||(this._array.sort(r.compareByGeneratedPos...
  class u (line 1) | class u{constructor(e,n){return e==a?Promise.resolve(this):function(e,n)...
    method constructor (line 1) | constructor(e,n){return e==a?Promise.resolve(this):function(e,n){let t...
    method initialize (line 1) | static initialize(e){s.initialize(e["lib/mappings.wasm"])}
    method fromSourceMap (line 1) | static fromSourceMap(e,n){return function(e,n){return c.fromSourceMap(...
    method with (line 1) | static async with(e,n,t){const r=await new u(e,n);try{return await t(r...
    method _parseMappings (line 1) | _parseMappings(e,n){throw new Error("Subclasses must implement _parseM...
    method eachMapping (line 1) | eachMapping(e,n,t){throw new Error("Subclasses must implement eachMapp...
    method allGeneratedPositionsFor (line 1) | allGeneratedPositionsFor(e){throw new Error("Subclasses must implement...
    method destroy (line 1) | destroy(){throw new Error("Subclasses must implement destroy")}
  class c (line 1) | class c extends u{constructor(e,n){return super(a).then(t=>{let o=e;"str...
    method constructor (line 1) | constructor(e,n){return super(a).then(t=>{let o=e;"string"==typeof e&&...
    method _findSourceIndex (line 1) | _findSourceIndex(e){let n=e;if(null!=this.sourceRoot&&(n=r.relative(th...
    method fromSourceMap (line 1) | static fromSourceMap(e,n){return new c(e.toString())}
    method sources (line 1) | get sources(){return this._absoluteSources.slice()}
    method _getMappingsPtr (line 1) | _getMappingsPtr(){return 0===this._mappingsPtr&&this._parseMappings(th...
    method _parseMappings (line 1) | _parseMappings(e,n){const t=e.length,r=this._wasm.exports.allocate_map...
    method eachMapping (line 1) | eachMapping(e,n,t){const o=n||null,i=t||u.GENERATED_ORDER,s=this.sourc...
    method allGeneratedPositionsFor (line 1) | allGeneratedPositionsFor(e){let n=r.getArg(e,"source");const t=r.getAr...
    method destroy (line 1) | destroy(){0!==this._mappingsPtr&&(this._wasm.exports.free_mappings(thi...
    method computeColumnSpans (line 1) | computeColumnSpans(){this._computedColumnSpans||(this._wasm.exports.co...
    method originalPositionFor (line 1) | originalPositionFor(e){const n={generatedLine:r.getArg(e,"line"),gener...
    method hasContentsOfAllSources (line 1) | hasContentsOfAllSources(){return!!this.sourcesContent&&(this.sourcesCo...
    method sourceContentFor (line 1) | sourceContentFor(e,n){if(!this.sourcesContent)return null;const t=this...
    method generatedPositionFor (line 1) | generatedPositionFor(e){let n=r.getArg(e,"source");if(n=this._findSour...
  class g (line 1) | class g extends u{constructor(e,n){return super(a).then(t=>{let o=e;"str...
    method constructor (line 1) | constructor(e,n){return super(a).then(t=>{let o=e;"string"==typeof e&&...
    method _generatedMappings (line 1) | get _generatedMappings(){return this.__generatedMappings||this._sortGe...
    method _originalMappings (line 1) | get _originalMappings(){return this.__originalMappings||this._sortOrig...
    method _generatedMappingsUnsorted (line 1) | get _generatedMappingsUnsorted(){return this.__generatedMappingsUnsort...
    method _originalMappingsUnsorted (line 1) | get _originalMappingsUnsorted(){return this.__originalMappingsUnsorted...
    method _sortGeneratedMappings (line 1) | _sortGeneratedMappings(){const e=this._generatedMappingsUnsorted;e.sor...
    method _sortOriginalMappings (line 1) | _sortOriginalMappings(){const e=this._originalMappingsUnsorted;e.sort(...
    method sources (line 1) | get sources(){const e=[];for(let n=0;n<this._sections.length;n++)for(l...
    method originalPositionFor (line 1) | originalPositionFor(e){const n={generatedLine:r.getArg(e,"line"),gener...
    method hasContentsOfAllSources (line 1) | hasContentsOfAllSources(){return this._sections.every((function(e){ret...
    method sourceContentFor (line 1) | sourceContentFor(e,n){for(let n=0;n<this._sections.length;n++){const t...
    method generatedPositionFor (line 1) | generatedPositionFor(e){for(let n=0;n<this._sections.length;n++){const...
    method _parseMappings (line 1) | _parseMappings(e,n){const t=this.__generatedMappingsUnsorted=[],o=this...
    method eachMapping (line 1) | eachMapping(e,n,t){const o=n||null;let i;switch(t||u.GENERATED_ORDER){...
    method _findMapping (line 1) | _findMapping(e,n,t,r,i,s){if(e[t]<=0)throw new TypeError("Line must be...
    method allGeneratedPositionsFor (line 1) | allGeneratedPositionsFor(e){const n=r.getArg(e,"line"),t={source:r.get...
    method destroy (line 1) | destroy(){for(let e=0;e<this._sections.length;e++)this._sections[e].co...
  function o (line 1) | function o(){this.generatedLine=0,this.generatedColumn=0,this.lastGenera...
  method mapping_callback (line 1) | mapping_callback(n,t,r,i,s,l,a,u,c,g){const p=new o;p.generatedLine=n+1,...
  method start_all_generated_locations_for (line 1) | start_all_generated_locations_for(){console.time("all_generated_location...
  method end_all_generated_locations_for (line 1) | end_all_generated_locations_for(){console.timeEnd("all_generated_locatio...
  method start_compute_column_spans (line 1) | start_compute_column_spans(){console.time("compute_column_spans")}
  method end_compute_column_spans (line 1) | end_compute_column_spans(){console.timeEnd("compute_column_spans")}
  method start_generated_location_for (line 1) | start_generated_location_for(){console.time("generated_location_for")}
  method end_generated_location_for (line 1) | end_generated_location_for(){console.timeEnd("generated_location_for")}
  method start_original_location_for (line 1) | start_original_location_for(){console.time("original_location_for")}
  method end_original_location_for (line 1) | end_original_location_for(){console.timeEnd("original_location_for")}
  method start_parse_mappings (line 1) | start_parse_mappings(){console.time("parse_mappings")}
  method end_parse_mappings (line 1) | end_parse_mappings(){console.timeEnd("parse_mappings")}
  method start_sort_by_generated_location (line 1) | start_sort_by_generated_location(){console.time("sort_by_generated_locat...
  method end_sort_by_generated_location (line 1) | end_sort_by_generated_location(){console.timeEnd("sort_by_generated_loca...
  method start_sort_by_original_location (line 1) | start_sort_by_original_location(){console.time("sort_by_original_locatio...
  method end_sort_by_original_location (line 1) | end_sort_by_original_location(){console.timeEnd("sort_by_original_locati...
  class l (line 1) | class l{constructor(e,n,t,r,o){this.children=[],this.sourceContents={},t...
    method constructor (line 1) | constructor(e){e||(e={}),this._file=o.getArg(e,"file",null),this._sour...
    method fromSourceMap (line 1) | static fromSourceMap(e){const n=e.sourceRoot,t=new l({file:e.file,sour...
    method addMapping (line 1) | addMapping(e){const n=o.getArg(e,"generated"),t=o.getArg(e,"original",...
    method setSourceContent (line 1) | setSourceContent(e,n){let t=e;null!=this._sourceRoot&&(t=o.relative(th...
    method applySourceMap (line 1) | applySourceMap(e,n,t){let r=n;if(null==n){if(null==e.file)throw new Er...
    method _validateMapping (line 1) | _validateMapping(e,n,t,r){if(n&&"number"!=typeof n.line&&"number"!=typ...
    method _serializeMappings (line 1) | _serializeMappings(){let e,n,t,i,s=0,l=1,a=0,u=0,c=0,g=0,p="";const h=...
    method _generateSourcesContent (line 1) | _generateSourcesContent(e,n){return e.map((function(e){if(!this._sourc...
    method toJSON (line 1) | toJSON(){const e={version:this._version,sources:this._sources.toArray(...
    method toString (line 1) | toString(){return JSON.stringify(this.toJSON())}
    method constructor (line 1) | constructor(e,n,t,r,o){this.children=[],this.sourceContents={},this.li...
    method fromStringWithSourceMap (line 1) | static fromStringWithSourceMap(e,n,t){const r=new l,s=e.split(i);let a...
    method add (line 1) | add(e){if(Array.isArray(e))e.forEach((function(e){this.add(e)}),this);...
    method prepend (line 1) | prepend(e){if(Array.isArray(e))for(let n=e.length-1;n>=0;n--)this.prep...
    method walk (line 1) | walk(e){let n;for(let t=0,r=this.children.length;t<r;t++)n=this.childr...
    method join (line 1) | join(e){let n,t;const r=this.children.length;if(r>0){for(n=[],t=0;t<r-...
    method replaceRight (line 1) | replaceRight(e,n){const t=this.children[this.children.length-1];return...
    method setSourceContent (line 1) | setSourceContent(e,n){this.sourceContents[o.toSetString(e)]=n}
    method walkSourceContents (line 1) | walkSourceContents(e){for(let n=0,t=this.children.length;n<t;n++)this....
    method toString (line 1) | toString(){let e="";return this.walk((function(n){e+=n})),e}
    method toStringWithSourceMap (line 1) | toStringWithSourceMap(e){const n={code:"",line:1,column:0},t=new r(e);...

FILE: client/src/js/overrides.js
  function requestPromisfied (line 274) | function requestPromisfied (options) {
  function onMouseDown (line 914) | function onMouseDown(e){
  function onRender (line 945) | function onRender() {

FILE: client/src/js/review.js
  function addReview (line 1) | async function addReview( params ) {

FILE: client/src/js/stigAdmin.js
  function addStigAdmin (line 1) | function addStigAdmin( params ) {

FILE: client/src/js/stigman.js
  function GetXmlHttpObject (line 8) | function GetXmlHttpObject() {
  function myContextMenu (line 22) | function myContextMenu (e,t,eOpts) {
  function start (line 30) | async function start () {
  function loadApp (line 62) | async function loadApp () {
  function broadcastHandler (line 284) | function broadcastHandler (event)  {
  function reauthenticate (line 305) | function reauthenticate({ codeVerifier, redirect, state, isIdle }) {

FILE: client/src/js/stigmanUtils.js
  function renderPct (line 3) | function renderPct ( v, m, r ) {
  function renderPctAllHigh (line 17) | function renderPctAllHigh ( v, m, r, ri, ci, s ) {
  function durationToNow (line 31) | function durationToNow(date, ago = false) {
  function renderDurationToNow (line 58) | function renderDurationToNow(date, md = {}) {
  function initProgress (line 71) | function initProgress (title,text,storeId,iframe) {
  function updateProgress (line 155) | function updateProgress (value,text) {
  function updateStatusText (line 160) | function updateStatusText (text, noNL, replace) {
  function resetProgress (line 172) | function resetProgress () {
  function closeProgress (line 177) | function closeProgress () {
  function reloadStore (line 182) | function reloadStore (id) {
  function Sm_HistoryData (line 187) | function Sm_HistoryData (idAppend) {
  function sortGroupId (line 439) | function sortGroupId (groupId) {
  function sortRuleId (line 451) | function sortRuleId (ruleId) {
  function sortSeverity (line 463) | function sortSeverity (severity) {
  function getFileIcon (line 476) | function getFileIcon (filename) {
  function encodeSm (line 504) | function encodeSm (sm,field) {
  function renderResult (line 513) | function renderResult(val, metaData, record, rowIndex, colIndex, store) {
  function renderEngineResult (line 518) | function renderEngineResult(val, metadata) {
  function renderStatuses (line 542) | function renderStatuses(val, metaData, record, rowIndex, colIndex, store) {
  function renderStatus (line 577) | function renderStatus(val) {
  function columnWrap (line 606) | function columnWrap(val, meta){
  function getRiskClass (line 612) | function getRiskClass(riskRating) {
  function calculateCoraRiskRating (line 623) | function calculateCoraRiskRating(metrics) {

FILE: client/src/js/workers/oidc-worker.js
  constant ENV (line 8) | let ENV = null
  function getAccessToken (line 37) | function getAccessToken() {
  function exchangeCodeForToken (line 48) | async function exchangeCodeForToken({ code, codeVerifier, clientId = ENV...
  function initialize (line 79) | async function initialize(options) {
  function getStatus (line 105) | async function getStatus() {
  function logout (line 114) | function logout() {
  function onMessage (line 121) | async function onMessage(e) {
  function dec2hex (line 144) | function dec2hex(dec) {
  function generateRandomString (line 148) | function generateRandomString() {
  function sha256 (line 154) | async function sha256(plain) {
  function base64UrlEncode (line 160) | function base64UrlEncode(a) {
  function challengeFromVerifier (line 170) | async function challengeFromVerifier(v) {
  function decodeToken (line 176) | function decodeToken(str) {
  function validateOidcConfiguration (line 195) | function validateOidcConfiguration() {
  function getScopeStr (line 224) | function getScopeStr() {
  function fetchOpenIdConfiguration (line 241) | async function fetchOpenIdConfiguration() {
  function createAuthorization (line 254) | async function createAuthorization(_redirectUri = redirectUri) {
  function getPkce (line 275) | async function getPkce() {
  function broadcastNoToken (line 281) | async function broadcastNoToken() {
  function broadcastToken (line 291) | function broadcastToken() {
  function clearAccessTokenTimer (line 299) | function clearAccessTokenTimer() {
  function clearRefreshTokenTimer (line 306) | function clearRefreshTokenTimer() {
  function setAccessTokenTimer (line 313) | function setAccessTokenTimer(delayMs) {
  function setRefreshTokenTimer (line 324) | function setRefreshTokenTimer(delayMs) {
  function getTokenTimes (line 334) | function getTokenTimes(token, timeoutBufferS = 10) {
  function setTokensAccessOnly (line 364) | function setTokensAccessOnly(tokensResponse) {
  function setTokensWithRefresh (line 380) | function setTokensWithRefresh(tokensResponse) {
  function validateTokensResponse (line 412) | function validateTokensResponse(tokensResponse) {
  function validateScope (line 425) | function validateScope(scopeValue, isAdmin = false) {
  function validateClaims (line 457) | function validateClaims(payload) {
  function validateAudience (line 483) | function validateAudience(payload) {
  function setTokens (line 501) | function setTokens(tokensResponse) {
  function clearAccessToken (line 513) | function clearAccessToken(sendBroadcast = false) {
  function clearTokens (line 519) | function clearTokens(sendBroadcast = false) {
  function fetchTokens (line 527) | async function fetchTokens(params) {
  function refreshAccessToken (line 555) | async function refreshAccessToken() {
  function setIdleHandler (line 574) | function setIdleHandler() {

FILE: client/src/js/workers/service-worker.js
  function fetchAttachment (line 4) | async function fetchAttachment (url, init, attachment) {

FILE: client/src/js/workers/state-worker.js
  function initialize (line 39) | function initialize(options) {
  function getApiState (line 80) | async function getApiState() {
  function onMessage (line 92) | async function onMessage(e) {
  function reconnectSSE (line 110) | function reconnectSSE() {
  function addListeners (line 128) | function addListeners() {

FILE: test/api/mocha/data/asset/assetPost.test.js
  function assetGetToPost (line 796) | function assetGetToPost (assetGet) {
  function stigsGetToPost (line 808) | function stigsGetToPost (stigsGetArray) {

FILE: test/api/mocha/integration/collection.test.js
  function assetGetToPost (line 1845) | function assetGetToPost (assetGet) {
  function stigsGetToPost (line 1857) | function stigsGetToPost (stigsGetArray) {

FILE: test/api/mocha/integration/job.test.js
  function runImmediateJob (line 541) | async function runImmediateJob(jobId) {
  function runImmediateTask (line 548) | async function runImmediateTask(taskname) {
  function deleteTestJobs (line 565) | async function deleteTestJobs() {
  function waitForRunFinish (line 574) | async function waitForRunFinish(runId, timeoutSeconds = 30) {

FILE: test/api/mocha/integration/logStream.test.js
  function openSocket (line 194) | async function openSocket() {

FILE: test/api/mocha/security/reviewCrossCollectionWrite.test.js
  function getVictimReview (line 113) | async function getVictimReview () {

FILE: test/state/mocha/lib.js
  function spawnApiPromise (line 25) | function spawnApiPromise ({
  function spawnApi (line 88) | function spawnApi ({
  function waitForLog (line 130) | function waitForLog (api, type, { count = 1, since = 0, predicate = null...
  function waitChildClose (line 150) | function waitChildClose (child) {
  function getPorts (line 164) | function getPorts (basePort) {
  function simpleRequest (line 180) | async function simpleRequest(url, method) {
  function bearerRequest (line 196) | async function bearerRequest({url, method, token}) {
  function spawnMySQL (line 225) | function spawnMySQL ({
  function spawnHttpServer (line 280) | function spawnHttpServer ({
  function execIpTables (line 288) | function execIpTables (args) {

FILE: test/unit/mocha/asyncApiValidator.test.js
  function minimalSpec (line 15) | function minimalSpec(overrides = {}) {
  function tempSpec (line 63) | function tempSpec(content) {

FILE: test/utils/appdata-update.js
  function main (line 9) | async function main() {
  function loadAndExportAllAppData (line 44) | async function loadAndExportAllAppData (appdataDir = '../api/appdata')
  function exportAppData (line 90) | async function exportAppData (options = {})
  function loadAppData (line 108) | async function loadAppData (appdataDir = '../api/appdata', appdataFileNa...

FILE: test/utils/mockOidc.js
  class MockOidc (line 8) | class MockOidc {
    method constructor (line 9) | constructor ({includeInsecureKid = false, keyCount = 1} = {}) {
    method rotateKeys (line 17) | rotateKeys ({includeInsecureKid = false, keyCount = 1} = {}) {
    method createKeyId (line 35) | createKeyId (publicKey) {
    method createInsecureKey (line 47) | createInsecureKey () {
    method getJwks (line 71) | getJwks () {
    method getMetadata (line 77) | getMetadata (request = {}) {
    method getToken (line 104) | getToken({
    method getCustomToken (line 188) | getCustomToken ({payload, privateKey, options}) {
    method getRefreshToken (line 192) | getRefreshToken ({sid, expiresIn = '1h', algorithm = 'RS256', kid}) {
    method getAuthHtml (line 215) | getAuthHtml({ state, redirect_uri, response_mode, prefix } = {}) {
    method parseQueryParams (line 430) | parseQueryParams(request) {
    method onRequest (line 446) | onRequest (request, response) {
    method start (line 714) | start ({port = 8080}) {
    method stop (line 726) | stop () {
Copy disabled (too large) Download .json
Condensed preview — 613 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (28,000K chars).
[
  {
    "path": ".dockerignore",
    "chars": 126,
    "preview": "**/node_modules\n**/state.json\n**/README.md\n**/.git\n**/.gitignore\n**/data\n**/test\n**/uploads\n**/docker\n!client/**/node_mo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report-form.yml",
    "chars": 2869,
    "preview": "name: 🐞 Bug Report\ndescription: File a bug/issue\ntitle: \"***The title of your Issue here***\"\nlabels: [Bug, Needs Triage]"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 621,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: 'FEATURE REQUEST: '\nlabels: enhancement\nassigne"
  },
  {
    "path": ".github/workflows/api-audit-test-coverage-response.yml",
    "chars": 7190,
    "preview": "name: API source\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n      - test-coverage\n    paths:\n  "
  },
  {
    "path": ".github/workflows/api-binary-tests.yml",
    "chars": 4596,
    "preview": "\nname: Build and Test Linux Binary\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n    paths:\n      "
  },
  {
    "path": ".github/workflows/api-container-tests.yml",
    "chars": 5324,
    "preview": "name: API containers\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n    paths:\n      - \"api/source/"
  },
  {
    "path": ".github/workflows/api-spec-validation.yml",
    "chars": 700,
    "preview": "name: API spec validation\r\non:\r\n  workflow_dispatch:\r\n  pull_request:\r\n    branches:\r\n      - main\r\n    paths:\r\n      - "
  },
  {
    "path": ".github/workflows/api-state-tests.yml",
    "chars": 1148,
    "preview": "name: API state tests\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n    paths:\n      - \"api/source"
  },
  {
    "path": ".github/workflows/build-binary-artifacts.yml",
    "chars": 3016,
    "preview": "\nname: Build Binary Artifacts and Sign\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - main\n    paths:\n      - 'a"
  },
  {
    "path": ".github/workflows/build-client.yml",
    "chars": 559,
    "preview": "name: Build client\non:\n  workflow_dispatch:\n  workflow_call:\njobs:\n  builder:\n    name: builder\n    runs-on: ubuntu-late"
  },
  {
    "path": ".github/workflows/build-docs.yml",
    "chars": 488,
    "preview": "name: Build docs\non:\n  workflow_dispatch:\n  workflow_call:\njobs:\n  builder:\n    name: builder\n    runs-on: ubuntu-latest"
  },
  {
    "path": ".github/workflows/client-sonarcloud.yml",
    "chars": 2109,
    "preview": "name: Client SonarCloud\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n    paths:\n      - \"client/s"
  },
  {
    "path": ".github/workflows/pub-docker.yml",
    "chars": 4707,
    "preview": "name: Publish Docker images\nenv:\n  DOCKERHUB_REPOSITORY: nuwcdivnpt/stig-manager\non:\n  workflow_dispatch:\n  push:\n    br"
  },
  {
    "path": ".github/workflows/unit-tests.yml",
    "chars": 811,
    "preview": "name: Unit tests\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n    paths:\n      - \"api/source/**\"\n"
  },
  {
    "path": ".readthedocs.yml",
    "chars": 626,
    "preview": "# .readthedocs.yml\r\n# Read the Docs configuration file\r\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html "
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4238,
    "preview": "# Contributing to STIG Manager\n\n**NOTE: This CONTRIBUTING.md describes our software contribution policy. You do not need"
  },
  {
    "path": "CONTRIBUTORS.md",
    "chars": 1343,
    "preview": "# Contributors\n\n**By adding your name, email address, and copyright date below, you understand and agree to the terms of"
  },
  {
    "path": "Dockerfile",
    "chars": 1355,
    "preview": "# STIG Manager OSS\n# \n# COPY commands assume the following lines in .dockerignore\n# **/node_modules\n# **/state.json\n# **"
  },
  {
    "path": "INTENT.md",
    "chars": 853,
    "preview": "# Licensing Intent\nThe intent is that this software and documentation (\"Project\") should be treated as if it is licensed"
  },
  {
    "path": "LICENSE.md",
    "chars": 37077,
    "preview": "\r\n---\r\n\r\n*For all code except the STIG Manager client*\r\n\r\n---\r\n\r\n## MIT License\r\n\r\n```\r\nCopyright (c) 2020-2026 U.S. Fed"
  },
  {
    "path": "README.md",
    "chars": 7607,
    "preview": "# STIG Manager\n\nSTIG Manager is an API and web client for managing STIG assessments of Information Systems, sponsored by"
  },
  {
    "path": "SECURITY.md",
    "chars": 2896,
    "preview": "# Security Policy\n\n## Supported Versions\n\nThe STIG Manager Team makes every effort to produce secure software. The proje"
  },
  {
    "path": "api/README.md",
    "chars": 468,
    "preview": "# STIG Manager API for Node.js\n\n## Required Node version\nThe API requires Node 14.0.0 or greater\n\n## Building binaries\n-"
  },
  {
    "path": "api/bin/.gitignore",
    "chars": 238,
    "preview": "## Directory for the STIG Manager API binaries\n\n# Content can be written here by executing:\n# $ ../build.sh\n#\n# This fil"
  },
  {
    "path": "api/build.sh",
    "chars": 1525,
    "preview": "#!/bin/bash\n\n# This file is used to build API binaries on the team workstations. It is not tested elsewhere, yet.\n# Requ"
  },
  {
    "path": "api/dist/.gitignore",
    "chars": 251,
    "preview": "## Directory for the STIG Manager API distribution archives\n\n# Content can be written here by executing:\n# $ ../build.sh"
  },
  {
    "path": "api/launchers/gen-launchers.py",
    "chars": 1589,
    "preview": "#!/usr/bin/python3\nimport sys\nimport os\nimport io\nimport csv\nimport textwrap\n\nif len(sys.argv) > 1 and sys.argv[1] == 'w"
  },
  {
    "path": "api/launchers/stig-manager.bat",
    "chars": 28068,
    "preview": "::==============================================================================\r\n:: STIGMAN_API_ADDRESS\r\n::\r\n::  | Defa"
  },
  {
    "path": "api/launchers/stig-manager.sh",
    "chars": 26968,
    "preview": "#==============================================================================\n# STIGMAN_API_ADDRESS\n#\n#  | Default: \"0"
  },
  {
    "path": "api/nuwcdivnpt-bot.gpg.asc",
    "chars": 2264,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQENBGXcsB0BCADIpexQoymA+0AGb9ojtisErQ5cp+xWv3SlPd5kOhuCpbhRhTnB\nyQMBr50jqpPZeDtV8"
  },
  {
    "path": "api/pkg.config.json",
    "chars": 559,
    "preview": "{\n    \"name\": \"stig-manager\",\n    \"pkg\": {\n        \"scripts\": [\"./source/controllers/**/*.js\", \"./source/service/**/*.js"
  },
  {
    "path": "api/source/README.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "api/source/bootstrap/bootstrapUtils.js",
    "chars": 1602,
    "preview": "const path = require('node:path')\nconst logger = require('../utils/logger')\nconst extensionCheck = require('./extensionC"
  },
  {
    "path": "api/source/bootstrap/client.js",
    "chars": 3135,
    "preview": "const express = require('express')\nconst path = require('path')\nconst writer = require('../utils/writer')\nconst logger ="
  },
  {
    "path": "api/source/bootstrap/dependencies.js",
    "chars": 561,
    "preview": "const logger = require('../utils/logger')\nconst auth = require('../utils/auth')\nconst db = require('../service/utils')\nc"
  },
  {
    "path": "api/source/bootstrap/docs.js",
    "chars": 2074,
    "preview": "\nconst express = require('express')\nconst path = require('path')\nconst fs = require('fs')\nconst logger = require('../uti"
  },
  {
    "path": "api/source/bootstrap/errorHandlers.js",
    "chars": 1232,
    "preview": "const logger = require('../utils/logger')\nconst smErrors = require('../utils/error')\nconst { serializeError } = require("
  },
  {
    "path": "api/source/bootstrap/extensionCheck.js",
    "chars": 271,
    "preview": "const SmError = require('../utils/error')\n\nfunction extensionCheck(req, res, next) {\n  if (req.openapi?.schema['x-elevat"
  },
  {
    "path": "api/source/bootstrap/middlewares.js",
    "chars": 3290,
    "preview": "\nconst path = require('node:path')\nconst multer  = require('multer')\nconst express = require('express')\nconst cors = req"
  },
  {
    "path": "api/source/bootstrap/server.js",
    "chars": 3236,
    "preview": "const logger = require('../utils/logger')\nconst path = require('node:path')\nconst logSocket = require('../utils/logSocke"
  },
  {
    "path": "api/source/bootstrap/signals.js",
    "chars": 491,
    "preview": "const state = require('../utils/state')\nconst logger = require('../utils/logger')\n\n// This function sets up signal handl"
  },
  {
    "path": "api/source/controllers/Asset.js",
    "chars": 20744,
    "preview": "'use strict';\n\nconst writer = require('../utils/writer')\nconst config = require('../utils/config')\nconst escape = requir"
  },
  {
    "path": "api/source/controllers/Collection.js",
    "chars": 45822,
    "preview": "'use strict';\n\nconst writer = require('../utils/writer')\nconst config = require('../utils/config')\nconst escape = requir"
  },
  {
    "path": "api/source/controllers/Job.js",
    "chars": 4680,
    "preview": "const SmError = require('../utils/error');\nconst JobService = require(`../service/JobService`)\n\nconst userJobIdBase = 10"
  },
  {
    "path": "api/source/controllers/Metrics.js",
    "chars": 4694,
    "preview": "const config = require('../utils/config')\nconst MetricsService = require(`../service/MetricsService`)\nconst Collection ="
  },
  {
    "path": "api/source/controllers/Operation.js",
    "chars": 4919,
    "preview": "const config = require('../utils/config')\nconst OperationService = require(`../service/OperationService`)\nconst escape ="
  },
  {
    "path": "api/source/controllers/Review.js",
    "chars": 15524,
    "preview": "'use strict';\n\nconst config = require('../utils/config')\nconst ReviewService = require(`../service/ReviewService`)\nconst"
  },
  {
    "path": "api/source/controllers/STIG.js",
    "chars": 8343,
    "preview": "'use strict';\n\nconst config = require('../utils/config');\nconst SmError = require('../utils/error');\nconst parsers = req"
  },
  {
    "path": "api/source/controllers/User.js",
    "chars": 11282,
    "preview": "'use strict';\n\nconst config = require('../utils/config')\nconst UserService = require(`../service/UserService`)\nconst Ass"
  },
  {
    "path": "api/source/healthcheck.js",
    "chars": 508,
    "preview": "const http = require(\"http\")\n\nconst options = {  \n    host : \"localhost\",\n    port: process.env.STIGMAN_API_PORT || 5400"
  },
  {
    "path": "api/source/index.js",
    "chars": 1217,
    "preview": "'use strict'\nconst startTime = process.hrtime.bigint()\nconst express = require('express')\nconst logger = require('./util"
  },
  {
    "path": "api/source/package.json",
    "chars": 1151,
    "preview": "{\n  \"name\": \"stig-management-api\",\n  \"version\": \"1.6.9\",\n  \"description\": \"An API for managing evaluations of Security T"
  },
  {
    "path": "api/source/service/AssetService.js",
    "chars": 59740,
    "preview": "'use strict';\nconst { randomUUID } = require('node:crypto')\nconst dbUtils = require('./utils')\nconst config = require('."
  },
  {
    "path": "api/source/service/CollectionService.js",
    "chars": 102246,
    "preview": "'use strict';\nconst dbUtils = require('./utils')\nconst config = require('../utils/config.js')\nconst MyController = requi"
  },
  {
    "path": "api/source/service/JobService.js",
    "chars": 10705,
    "preview": "const { randomUUID } = require('node:crypto')\nconst dbUtils = require('./utils')\nconst _this = this\n\nexports.queryJobs ="
  },
  {
    "path": "api/source/service/MetricsService.js",
    "chars": 24349,
    "preview": "const dbUtils = require('./utils')\n\nfunction genLabelPredicates ({labelNames, labelIds, labelMatch, collectionLabelTable"
  },
  {
    "path": "api/source/service/OperationService.js",
    "chars": 33486,
    "preview": "'use strict';\nconst dbUtils = require('./utils')\nconst config = require('../utils/config')\nconst logger = require('../ut"
  },
  {
    "path": "api/source/service/ReviewService.js",
    "chars": 48024,
    "preview": "'use strict';\nconst dbUtils = require('./utils')\n\nlet _this = this\n\nexports.postReviewBatch = async function ({\n  source"
  },
  {
    "path": "api/source/service/STIGService.js",
    "chars": 43361,
    "preview": "'use strict';\nconst dbUtils = require('./utils')\nconst {createHash} = require('node:crypto')\n\nconst _this = this\n\nfuncti"
  },
  {
    "path": "api/source/service/UserService.js",
    "chars": 19153,
    "preview": "'use strict';\nconst config = require('../utils/config');\nconst SmError = require('../utils/error');\nconst dbUtils = requ"
  },
  {
    "path": "api/source/service/migrations/0000.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0001.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0002.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0003.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0004.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0005.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0006.js",
    "chars": 1759,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0007.js",
    "chars": 1728,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  'SET FOREIGN_KEY_CHECKS=0',\n  'ALTER"
  },
  {
    "path": "api/source/service/migrations/0008.js",
    "chars": 773,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  'ALTER TABLE asset MODIFY COLUMN nam"
  },
  {
    "path": "api/source/service/migrations/0009.js",
    "chars": 489,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  'ALTER TABLE review ADD COLUMN metad"
  },
  {
    "path": "api/source/service/migrations/0010.js",
    "chars": 3642,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `\n    ALTER TABLE stig_asset_map \n  "
  },
  {
    "path": "api/source/service/migrations/0011.js",
    "chars": 2306,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE review\n  CHANGE COLUMN "
  },
  {
    "path": "api/source/service/migrations/0012.js",
    "chars": 2450,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE collection DROP COLUMN "
  },
  {
    "path": "api/source/service/migrations/0013.js",
    "chars": 1584,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `CREATE TABLE collection_label (\n   "
  },
  {
    "path": "api/source/service/migrations/0014.js",
    "chars": 858,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE review ADD COLUMN resul"
  },
  {
    "path": "api/source/service/migrations/0015.js",
    "chars": 1968,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `UPDATE review SET resultEngine = NU"
  },
  {
    "path": "api/source/service/migrations/0016.js",
    "chars": 7370,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `\n  ALTER TABLE stig_asset_map \n  RE"
  },
  {
    "path": "api/source/service/migrations/0017.js",
    "chars": 4303,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n\t`ALTER TABLE current_rev DROP COLUMN "
  },
  {
    "path": "api/source/service/migrations/0018.js",
    "chars": 1041,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE stig_asset_map ADD COLU"
  },
  {
    "path": "api/source/service/migrations/0019.js",
    "chars": 4423,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE revision \n  ADD COLUMN "
  },
  {
    "path": "api/source/service/migrations/0020.js",
    "chars": 6955,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  // if absent here, the query UPDATE "
  },
  {
    "path": "api/source/service/migrations/0021.js",
    "chars": 1001,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `DELETE FROM current_rev`,\n  `INSERT"
  },
  {
    "path": "api/source/service/migrations/0022.js",
    "chars": 7750,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n\n  // table: rule_version_check_digest"
  },
  {
    "path": "api/source/service/migrations/0023.js",
    "chars": 3588,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n\n  // table: revision\n  `ALTER TABLE r"
  },
  {
    "path": "api/source/service/migrations/0024.js",
    "chars": 1287,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n\n  // table: collection\n  `ALTER TABLE"
  },
  {
    "path": "api/source/service/migrations/0025.js",
    "chars": 680,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n\n  // table: collection\n  `ALTER TABLE"
  },
  {
    "path": "api/source/service/migrations/0026.js",
    "chars": 592,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n\n  // table: collection\n  `ALTER TABLE"
  },
  {
    "path": "api/source/service/migrations/0027.js",
    "chars": 710,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE result \n  ADD COLUMN ck"
  },
  {
    "path": "api/source/service/migrations/0028.js",
    "chars": 543,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  // table: review\n  `ALTER TABLE revi"
  },
  {
    "path": "api/source/service/migrations/0029.js",
    "chars": 455,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `DROP VIEW IF EXISTS v_current_group"
  },
  {
    "path": "api/source/service/migrations/0032.js",
    "chars": 1302,
    "preview": "const logger = require('../../utils/logger')\nconst path = require('node:path')\n\nconst migrationName = path.basename(__fi"
  },
  {
    "path": "api/source/service/migrations/0033.js",
    "chars": 577,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `UPDATE collection\n   SET settings ="
  },
  {
    "path": "api/source/service/migrations/0034.js",
    "chars": 479,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE asset ADD INDEX idx_sta"
  },
  {
    "path": "api/source/service/migrations/0035.js",
    "chars": 470,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE review_history CHANGE C"
  },
  {
    "path": "api/source/service/migrations/0036.js",
    "chars": 4841,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `DROP TABLE IF EXISTS collection_gra"
  },
  {
    "path": "api/source/service/migrations/0037.js",
    "chars": 1663,
    "preview": "const logger = require('../../utils/logger')\nconst path = require('node:path')\n\nconst migrationName = path.basename(__fi"
  },
  {
    "path": "api/source/service/migrations/0038.js",
    "chars": 3165,
    "preview": "const logger = require('../../utils/logger')\r\nconst path = require('node:path')\r\n\r\nconst migrationName = path.basename(_"
  },
  {
    "path": "api/source/service/migrations/0039.js",
    "chars": 3079,
    "preview": "const logger = require('../../utils/logger')\nconst path = require('node:path')\n\nconst migrationName = path.basename(__fi"
  },
  {
    "path": "api/source/service/migrations/0040.js",
    "chars": 1839,
    "preview": "const logger = require('../../utils/logger')\nconst path = require('node:path')\n\nconst migrationName = path.basename(__fi"
  },
  {
    "path": "api/source/service/migrations/0041.js",
    "chars": 6473,
    "preview": "const logger = require('../../utils/logger')\nconst path = require('node:path')\n\nconst migrationName = path.basename(__fi"
  },
  {
    "path": "api/source/service/migrations/0042.js",
    "chars": 1958,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `ALTER TABLE revision ADD COLUMN mar"
  },
  {
    "path": "api/source/service/migrations/0043.js",
    "chars": 1407,
    "preview": "const logger = require('../../utils/logger')\nconst path = require('node:path')\n\nconst migrationName = path.basename(__fi"
  },
  {
    "path": "api/source/service/migrations/0044.js",
    "chars": 1601,
    "preview": "const Importer = require('./lib/mysql-import.js')\nconst logger = require('../../utils/logger')\nconst path = require('pat"
  },
  {
    "path": "api/source/service/migrations/0045.js",
    "chars": 20729,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `DROP TABLE IF EXISTS job_task_map`,"
  },
  {
    "path": "api/source/service/migrations/0046.js",
    "chars": 13444,
    "preview": "const MigrationHandler = require('./lib/MigrationHandler')\n\nconst upMigration = [\n  `DROP PROCEDURE IF EXISTS get_runtim"
  },
  {
    "path": "api/source/service/migrations/lib/MigrationHandler.js",
    "chars": 1998,
    "preview": "\"use strict\";\n\nconst path = require('path')\nconst logger = require('../../../utils/logger')\n\nmodule.exports = class Migr"
  },
  {
    "path": "api/source/service/migrations/lib/mysql-import.js",
    "chars": 9617,
    "preview": "/**\n * mysql-import - v4.0.24\n * Import .sql into a MySQL database with Node.\n * @author Rob Parham\n * @website https://"
  },
  {
    "path": "api/source/service/migrations/lib/umzug-mysql-storage.js",
    "chars": 1563,
    "preview": "module.exports = class MyStorage {\n  constructor(options) {\n    this.pool = options.pool\n    this.hasMigrationTable = fa"
  },
  {
    "path": "api/source/service/migrations/sql/0000/up/10-stigman-schema.sql",
    "chars": 22408,
    "preview": "-- MySQL dump 10.13-csmig  Distrib 8.0.18-csmig, for Linux (x86_64)\n--\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, "
  },
  {
    "path": "api/source/service/migrations/sql/0000/up/31-stigman-static.sql",
    "chars": 2861,
    "preview": "-- MySQL dump 10.13  Distrib 8.0.18, for Linux (x86_64)\n--\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECK"
  },
  {
    "path": "api/source/service/migrations/sql/0000/up/32-cci-data.sql",
    "chars": 3123594,
    "preview": "-- MySQL dump 10.13-csmig  Distrib 8.0.18-csmig, for Linux (x86_64)\n--\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, "
  },
  {
    "path": "api/source/service/migrations/sql/0001/down/10-collection-created.sql",
    "chars": 49,
    "preview": "ALTER TABLE `collection` \nDROP COLUMN `created`;\n"
  },
  {
    "path": "api/source/service/migrations/sql/0001/up/10-collection-created.sql",
    "chars": 109,
    "preview": "ALTER TABLE `collection` \nADD COLUMN `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `metadata`;\n"
  },
  {
    "path": "api/source/service/migrations/sql/0002/down/10-collection-description.sql",
    "chars": 52,
    "preview": "ALTER TABLE `collection` \nDROP COLUMN `description`;"
  },
  {
    "path": "api/source/service/migrations/sql/0002/up/10-collection-description.sql",
    "chars": 82,
    "preview": "ALTER TABLE `collection` \nADD COLUMN `description` VARCHAR(255) NULL AFTER `name`;"
  },
  {
    "path": "api/source/service/migrations/sql/0003/up/10-asset-mac-fqdn.sql",
    "chars": 137,
    "preview": "ALTER TABLE `asset` \nADD COLUMN `mac` VARCHAR(17) NULL AFTER `ip`;\nALTER TABLE `asset` \nADD COLUMN `fqdn` VARCHAR(255) N"
  },
  {
    "path": "api/source/service/migrations/sql/0004/up/10-user-data.sql",
    "chars": 274,
    "preview": "ALTER TABLE `user_data` \nDROP COLUMN `display`,\nDROP COLUMN `email`,\nDROP COLUMN `globalAccess`,\nDROP COLUMN `canCreateC"
  },
  {
    "path": "api/source/service/migrations/sql/0005/down/10-v-current-rev.sql",
    "chars": 2341,
    "preview": "ALTER VIEW `v_current_rev` AS\nselect \n`rr`.`revId` AS `revId`,`rr`.`benchmarkId` AS `benchmarkId`,`rr`.`version` AS `ver"
  },
  {
    "path": "api/source/service/migrations/sql/0005/up/10-v-current-rev.sql",
    "chars": 2459,
    "preview": "ALTER VIEW `v_current_rev` AS\nselect \n\t`rr`.`revId` AS `revId`,\n\t`rr`.`benchmarkId` AS `benchmarkId`,\n\t`rr`.`version` AS"
  },
  {
    "path": "api/source/service/migrations/sql/0006/up/10-v-current-rev.sql",
    "chars": 2586,
    "preview": "ALTER VIEW `v_current_rev` AS\nselect \n\t`rr`.`revId` AS `revId`,\n\t`rr`.`benchmarkId` AS `benchmarkId`,\n\t`rr`.`version` AS"
  },
  {
    "path": "api/source/service/migrations/sql/current/10-stigman-tables.sql",
    "chars": 51651,
    "preview": "-- MySQL dump 10.13  Distrib 8.0.44, for Linux (x86_64)\n--\n-- Host: 127.0.0.1    Database: stigman\n-- ------------------"
  },
  {
    "path": "api/source/service/migrations/sql/current/20-stigman-static.sql",
    "chars": 6008,
    "preview": "-- MySQL dump 10.13  Distrib 8.0.44, for Linux (x86_64)\n--\n-- Host: 127.0.0.1    Database: stigman\n-- ------------------"
  },
  {
    "path": "api/source/service/migrations/sql/current/31-rev5-cci-data.sql",
    "chars": 2638235,
    "preview": "--\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_K"
  },
  {
    "path": "api/source/service/migrations/sql/generateSchema.sh",
    "chars": 2017,
    "preview": "#!/bin/bash\n\n# Use this script to generate the current schema and static data for the 'stigman' database.\n# It will prod"
  },
  {
    "path": "api/source/service/utils.js",
    "chars": 32708,
    "preview": "const mysql = require('mysql2/promise')\nconst config = require('../utils/config')\nconst logger = require('../utils/logge"
  },
  {
    "path": "api/source/specification/log-socket.yaml",
    "chars": 9689,
    "preview": "asyncapi: 3.0.0\ninfo:\n  title: Log Stream WebSocket API\n  version: 1.0.0\n  description: |\n    WebSocket API for streamin"
  },
  {
    "path": "api/source/specification/stig-manager.yaml",
    "chars": 316485,
    "preview": "openapi: 3.0.1\ninfo:\n  title: STIG Manager API\n  description: An API for managing evaluations of Security Technical Impl"
  },
  {
    "path": "api/source/tls/README.md",
    "chars": 55,
    "preview": "Optional: Place your TLS/SSL certificates and keys here"
  },
  {
    "path": "api/source/utils/PoolMonitor.js",
    "chars": 1942,
    "preview": "/**\n * Class representing a PoolMonitor.\n * Monitors the database connection status and determines if the API should ent"
  },
  {
    "path": "api/source/utils/asyncApiValidator.js",
    "chars": 6820,
    "preview": "/**\r\n * Lightweight AsyncAPI 3.0 message validator.\r\n *\r\n * Builds AJV-compiled validators from an AsyncAPI 3.0 YAML spe"
  },
  {
    "path": "api/source/utils/auth.js",
    "chars": 11440,
    "preview": "const config = require('./config')\r\nconst logger = require('./logger')\r\nconst jwt = require('jsonwebtoken')\r\nconst retry"
  },
  {
    "path": "api/source/utils/buffer-json.js",
    "chars": 1339,
    "preview": "function stringify (value, space) {\n    return JSON.stringify(value, replacer, space)\n  }\n  \n  function parse (text) {\n "
  },
  {
    "path": "api/source/utils/config.js",
    "chars": 6678,
    "preview": "const ourPackage = require(\"../package.json\")\n\n// Array of known insecure kid values\nconst insecureKids = ['FJ86GcF3jTbN"
  },
  {
    "path": "api/source/utils/error.js",
    "chars": 3762,
    "preview": "class SmError extends Error {\n  constructor(message) {\n    super(message)\n   // Ensure the name of this error is the sam"
  },
  {
    "path": "api/source/utils/escape.js",
    "chars": 1753,
    "preview": "\n\n/**\n * Escapes XML reserved characters with named entity references.\n * @param {string} value - The string to escape.\n"
  },
  {
    "path": "api/source/utils/jwksCache.js",
    "chars": 7819,
    "preview": "\nconst EventEmitter = require('node:events')\nconst crypto = require('node:crypto')\nconst http = require('node:http')\ncon"
  },
  {
    "path": "api/source/utils/klona.js",
    "chars": 799,
    "preview": "module.exports = function klona(val) {\n  // MIT License\n  // Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (luke"
  },
  {
    "path": "api/source/utils/log-schema.json",
    "chars": 10079,
    "preview": "{\n  \"$schema\": \"https://json-schema.org/draft-07/schema\",\n  \"$id\": \"http://yourdomain.com/schemas/myschema.json\",\n  \"typ"
  },
  {
    "path": "api/source/utils/logSocket.js",
    "chars": 8173,
    "preview": "const { randomUUID } = require('node:crypto')\nconst logger = require('./logger')\nconst WebSocket = require('ws')\nconst c"
  },
  {
    "path": "api/source/utils/logger.js",
    "chars": 10002,
    "preview": "\nconst { randomUUID } = require('node:crypto')\nconst onFinished = require('on-finished')\nconst onHeaders = require('on-h"
  },
  {
    "path": "api/source/utils/parsers.js",
    "chars": 5600,
    "preview": "const {XMLParser} = require('fast-xml-parser')\nconst he = require('he')\n\nmodule.exports.benchmarkFromXccdf = function (x"
  },
  {
    "path": "api/source/utils/roles.js",
    "chars": 96,
    "preview": "module.exports.ROLES = { \n    'Restricted': 1,\n    'Full': 2,\n    'Manage': 3,\n    'Owner': 4\n}\n"
  },
  {
    "path": "api/source/utils/serializeError.js",
    "chars": 4127,
    "preview": "// MIT License\n\n// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\n// Permission is her"
  },
  {
    "path": "api/source/utils/serializers.js",
    "chars": 3584,
    "preview": "const {promises: fs} = require('fs')\nconst path = require('path')\nconst XlsxTemplate = require('xlsx-template')\n\nmodule."
  },
  {
    "path": "api/source/utils/state.js",
    "chars": 4637,
    "preview": "const EventEmitter = require('events')\nconst logger = require('./logger')\n\n/**\n * Represents the state of the API.\n * @t"
  },
  {
    "path": "api/source/utils/writer.js",
    "chars": 1775,
    "preview": "const escape = require ('./escape.js')\nlet ResponsePayload = function(code, payload) {\n  this.code = code;\n  this.payloa"
  },
  {
    "path": "api/source/utils/xlsx-template-js-zip-upgrade/LICENSE",
    "chars": 1090,
    "preview": "Copyright (c) 2013-2018 Martin Aspeli, 2018-2020 Andrii Kurdiumov\n\nPermission is hereby granted, free of charge, to any "
  },
  {
    "path": "api/source/utils/xlsx-template-js-zip-upgrade/README.md",
    "chars": 6945,
    "preview": "# XLSX Template\n\n[![Build status](https://api.travis-ci.org/optilude/xlsx-template.png?branch=master)](http://travis-ci."
  },
  {
    "path": "api/source/utils/xlsx-template-js-zip-upgrade/lib/index.d.ts",
    "chars": 3684,
    "preview": "import * as etree from \"elementtree\";\nimport * as JSZip from \"jszip\";\n\nexport interface TemplatePlaceholder{\n    type: s"
  },
  {
    "path": "api/source/utils/xlsx-template-js-zip-upgrade/lib/index.js",
    "chars": 44112,
    "preview": "/*jshint globalstrict:true, devel:true */\n/*eslint no-var:0 */\n/*global require, module, Buffer */\n\"use strict\";\n\nvar pa"
  },
  {
    "path": "api/source/utils/xlsx-template-js-zip-upgrade/package.json",
    "chars": 820,
    "preview": "{\n  \"name\": \"xlsx-template\",\n  \"version\": \"1.2.0\",\n  \"description\": \"Generate .xlsx (Excel) files from templates built i"
  },
  {
    "path": "client/README.md",
    "chars": 649,
    "preview": "# STIG Manager Web App\n\n### Running the STIG Manager API and Web App from source\n\nYou must build the web app prior to st"
  },
  {
    "path": "client/build.sh",
    "chars": 4992,
    "preview": "#!/bin/bash\n\n# STIG Manager client distribution build script\n#\n# Requires nodejs and npm to install uglify-js\n# npm inst"
  },
  {
    "path": "client/dist/.gitignore",
    "chars": 245,
    "preview": "## Directory for the STIG Manager client distribution\n\n# Content can be written here by executing:\n# $ ../build.sh\n#\n# T"
  },
  {
    "path": "client/src/css/ColumnHeaderGroup.css",
    "chars": 242,
    "preview": "/*!\n * Ext JS Library 3.2.1\n * Copyright(c) 2006-2010 Ext JS, Inc.\n * licensing@extjs.com\n * http://www.extjs.com/licens"
  },
  {
    "path": "client/src/css/RowEditor.css",
    "chars": 2156,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/css/dark-mode.css",
    "chars": 222459,
    "preview": "/*! Portions were generated by Dark Reader | Licensed under MIT https://github.com/darkreader/darkreader/blob/master/LIC"
  },
  {
    "path": "client/src/css/init.css",
    "chars": 920,
    "preview": "\n#loading-mask {\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 20000;\n  display: "
  },
  {
    "path": "client/src/css/jsonview.bundle.css",
    "chars": 1536,
    "preview": ".json-container {\n  font-family: 'Open Sans';\n  font-size: 11px;\n  background-color: transparent;\n  color: #808080;\n  bo"
  },
  {
    "path": "client/src/css/stigman.css",
    "chars": 69444,
    "preview": ":root {\n  --metrics-status-chart-assessed-light: hsl(230deg 41% 86%);\n  --metrics-status-chart-submitted-light: hsl(92de"
  },
  {
    "path": "client/src/ext/INCLUDE_ORDER.txt",
    "chars": 860,
    "preview": "All adapter related files below are located in \n/adapters/<lib name>/ of this zip file.\n\nYour include order should be:\n\n"
  },
  {
    "path": "client/src/ext/adapter/ext/ext-base-debug.js",
    "chars": 113775,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/adapter/ext/ext-base.js",
    "chars": 30625,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/ext-all-debug-w-comments.js",
    "chars": 2868913,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/ext-all-debug.js",
    "chars": 1413745,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/ext-all.js",
    "chars": 720049,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/ext.jsb2",
    "chars": 48831,
    "preview": "{\n    \"projectName\": \"Ext JS\",\n    \"deployDir\": \".\",\n    \"licenseText\": \"\",\n    \"pkgs\": [{\n        \"name\": \"Ext Base\",\n "
  },
  {
    "path": "client/src/ext/gpl-3.0.txt",
    "chars": 35147,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "client/src/ext/index.html",
    "chars": 8193,
    "preview": "<!DOCTYPE HTML>\n<html>\n<head>\n<meta charset=\"UTF-8\" />\n<title>Welcome to Ext JS</title>\n<link rel=\"shortcut icon\" href=\""
  },
  {
    "path": "client/src/ext/license.txt",
    "chars": 1482,
    "preview": "Ext JS 3.4 - JavaScript Library\nCopyright (c) 2006-2013, Sencha Inc.\nAll rights reserved.\nlicensing@sencha.com\n\nhttp://w"
  },
  {
    "path": "client/src/ext/release-notes.html",
    "chars": 6816,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n<html>\n    <head>\n        <meta charset=\"UTF-8\">\n        <title>\n    "
  },
  {
    "path": "client/src/ext/resources/css/debug.css",
    "chars": 1465,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/ext-all-notheme.css",
    "chars": 101734,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/ext-all.css",
    "chars": 116466,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/reset-min.css",
    "chars": 1013,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/borders.css",
    "chars": 1605,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/box.css",
    "chars": 2064,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/button.css",
    "chars": 8643,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/combo.css",
    "chars": 1335,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/core.css",
    "chars": 6020,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/date-picker.css",
    "chars": 5298,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/dd.css",
    "chars": 1554,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/debug.css",
    "chars": 1102,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/dialog.css",
    "chars": 1646,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/editor.css",
    "chars": 3477,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/form.css",
    "chars": 11824,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/grid.css",
    "chars": 11795,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/layout.css",
    "chars": 5368,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/list-view.css",
    "chars": 2084,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/menu.css",
    "chars": 4495,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/panel-reset.css",
    "chars": 6824,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/panel.css",
    "chars": 8279,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/pivotgrid.css",
    "chars": 1818,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/progress.css",
    "chars": 1307,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/qtips.css",
    "chars": 3112,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/reset.css",
    "chars": 1169,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/resizable.css",
    "chars": 3432,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/slider.css",
    "chars": 2399,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/tabs.css",
    "chars": 8143,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  },
  {
    "path": "client/src/ext/resources/css/structure/toolbar.css",
    "chars": 5774,
    "preview": "/*\nThis file is part of Ext JS 3.4\n\nCopyright (c) 2011-2013 Sencha Inc\n\nContact:  http://www.sencha.com/contact\n\nGNU Gen"
  }
]

// ... and 413 more files (download for full content)

About this extraction

This page contains the full source code of the NUWCDIVNPT/stig-manager GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 613 files (25.8 MB), approximately 6.8M tokens, and a symbol index with 1301 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!