Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
config:
# Disable line-length rule — markdown prose doesn't benefit from hard wrapping
line-length: false
# Allow duplicate headings — API docs reuse "Request Example", "Response Example", etc.
no-duplicate-heading: false
# Allow emphasis as headings — docs use **bold** as sub-section labels
no-emphasis-as-heading: false
# Allow ordered list prefixes to continue across interruptions (1. 2. 3. not 1. 1. 1.)
ol-prefix: false
# Allow blank lines inside blockquotes — used for readability in docs
no-blanks-blockquote: false
# Allow fenced code blocks without language — not all snippets need syntax highlighting
fenced-code-language: false
# Allow files to start without an h1 — some files start with h2 or frontmatter
first-line-heading: false
# Allow heading level increments to skip (e.g. h2 -> h4) — docs structure varies
heading-increment: false
# Allow multiple top-level headings
single-title: false
# Allow indented code blocks alongside fenced — legacy docs use both styles
code-block-style: false
77 changes: 69 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,18 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-added-large-files
args: ['--maxkb=500']
- id: check-ast
- id: check-json
exclude: ^test/cdk/stacks/__baselines__/
- id: check-toml
- id: check-yaml
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: check-symlinks
- id: debug-statements
- id: mixed-line-ending
args: ['--fix=lf']
exclude: ^test/cdk/stacks/__baselines__/
Expand All @@ -46,14 +54,29 @@ repos:
exclude: ^test/cdk/stacks/__baselines__/
- id: trailing-whitespace
exclude: ^test/cdk/stacks/__baselines__/

- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
- id: name-tests-test
args: ['--pytest-test-first']
files: ^test/.*\.py$
exclude: (^test/cdk/|^test/integration/|__init__\.py$|README|conftest\.py$|integration_definitions\.py$|integration_test_utils\.py$|config_loader\.py$|list-integ-models\.py$|integration-setup-test\.py$)
- id: no-commit-to-branch
args: ['--branch', 'main', '--branch', 'mainline']

- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
- id: codespell
entry: codespell
args: ['--skip=*.git*,*cdk.out*,*venv*,*mypy_cache*,*package-lock*,*node_modules*,*dist/*,*/public/*,*poetry.lock*,*coverage*,*models/*,*htmlcov*,*TIKTOKEN_CACHE/*,*test/cdk/stacks/__baselines__/*,*.jsonl', "-L=xdescribe,assertIn,afterAll"]
pass_filenames: false
- id: python-check-mock-methods
- id: python-no-eval
- id: python-no-log-warn
- id: python-use-type-annotations

# NOTE: shellcheck-py fails to install in environments with custom CA certs
# (SSL: CERTIFICATE_VERIFY_FAILED). Install shellcheck locally and uncomment,
# or use `apt install shellcheck` / `brew install shellcheck` first.
# - repo: https://github.com/shellcheck-py/shellcheck-py
# rev: v0.11.0.1
# hooks:
# - id: shellcheck
# args: ['--severity=warning']

- repo: https://github.com/pycqa/isort
rev: 8.0.1
Expand All @@ -68,13 +91,37 @@ repos:
- id: black
exclude: ^test/cdk/stacks/__baselines__/

# NOTE: docformatter is incompatible with black — it removes the blank line
# before module docstrings, which violates PEP 8 E302 and black's formatting.
# Uncomment if the upstream issue is resolved:
# https://github.com/PyCQA/docformatter/issues
# - repo: https://github.com/PyCQA/docformatter
# rev: v1.7.8
# hooks:
# - id: docformatter
# args:
# - --in-place
# - --black
# - --wrap-summaries=120
# - --wrap-descriptions=120
# - --style=google
# exclude: ^test/cdk/stacks/__baselines__/

- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
hooks:
- id: codespell
entry: codespell
args: ['--skip=*.git*,*cdk.out*,*venv*,*mypy_cache*,*package-lock*,*node_modules*,*dist/*,*/public/*,*poetry.lock*,*coverage*,*models/*,*htmlcov*,*TIKTOKEN_CACHE/*,*test/cdk/stacks/__baselines__/*,*.jsonl', "-L=xdescribe,assertIn,afterAll"]
pass_filenames: false

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.15.11'
hooks:
- id: ruff-check
args:
- --exit-non-zero-on-fix
- --per-file-ignores=test/**/*.py:E402,test/**/*.py:PLC0415
- --per-file-ignores=test/**/*.py:E402,test/**/*.py:PLC0415,test/**/*.py:D
- --fix
exclude: (\.ipynb$|^test/cdk/stacks/__baselines__/)

Expand Down Expand Up @@ -120,6 +167,20 @@ repos:
- --no-warn-ignored
- --fix

- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.17.2
hooks:
- id: markdownlint-cli2
args: ['--fix']
exclude: (^node_modules/|^test/cdk/stacks/__baselines__/|CHANGELOG\.md$)

- repo: https://github.com/oxipng/oxipng
rev: v10.1.0
hooks:
- id: oxipng
args: ['-o', '4', '--strip', 'safe']
exclude: ^(node_modules/|lib/core/layers/)

# - repo: https://github.com/Lucas-C/pre-commit-hooks-safety
# rev: v1.3.2
# hooks:
Expand Down
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.
<opensource-codeofconduct@amazon.com> with any additional questions or comments.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Looking at the existing issues is a great way to find something to contribute on

This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.
<opensource-codeofconduct@amazon.com> with any additional questions or comments.

## Security issue notifications

Expand Down
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Instead, please report security issues by:
### 📝 What to Include

Please include the following information:

- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
Expand All @@ -33,21 +34,25 @@ Please include the following information:
## 🛡️ Security Measures in Place

### **Static Analysis**

- **CodeQL**: Automated security scanning on all pull requests
- **Dependency Scanning**: Regular vulnerability detection
- **License Compliance**: Automated license validation

### **Dependency Management**

- **Dependabot**: Automated security updates
- **Pin Dependencies**: Critical dependencies pinned by hash
- **Vulnerability Monitoring**: Continuous monitoring of known CVEs

### **CI/CD Security**

- **Least Privilege**: GitHub Actions use minimal required permissions
- **Supply Chain Protection**: All third-party actions pinned by commit hash
- **Secure Workflows**: No dangerous workflow patterns

### **Infrastructure Security**

- **Container Security**: Base images pinned to specific digests
- **AWS IAM**: Least privilege access controls
- **Encryption**: TLS 1.2+ for all communications
Expand Down
Empty file modified bin/lisa.ts
100644 → 100755
Empty file.
12 changes: 11 additions & 1 deletion cypress/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,27 @@
We maintain two suites of tests for our application:

### **Smoke Tests**

- *Isolation:* All network calls (including authentication) are fully **mocked out**.
- *Purpose:* Quickly verify that core UI components and routes render without hitting any backend.
- *Use Case:* Fast, lightweight sanity checks on every code change.

### **End‑to‑End (E2E) Tests**

- *Integration:* Execute complete user flows against a **live API** (or your local dev stack).
- *Coverage:* Real authentication, data fetches, and error‑handling paths.
- *Goal:* Ensure the entire system (frontend ↔ backend) works seamlessly together.

---

## Test Setup

In `cypress.e2e.config.ts` or `cypress.smoke.config.ts` the following environment variables need to be configured:

- `baseUrl` - set to either `http://localhost:3000/` or the URL of your dev stack (e.g. `https://<api gateway id>.execute-api.us-east-1.amazonaws.com/Prod/`).

#### Example setup for localhost:
#### Example setup for localhost

```
e2e: {
...
Expand All @@ -27,14 +32,17 @@ e2e: {
```

# Running the tests

If you are running the e2e tests, you will need to add the test account password to your env prior to executing the tests:

```
export TEST_ACCOUNT_PASSWORD=<password>

npm run cypress:e2e:run
```

You should get output like:

```
npm run cypress:e2e:run

Expand Down Expand Up @@ -106,13 +114,15 @@ DevTools listening on ws://127.0.0.1:51352/devtools/browser/2f804c68-414e-4004-9
```

## Run tests interactively

```
npm run cypress:e2e:open
```

# Linting

To ensure that code is meeting the enforced code standards you can run the following command within the `cypress` directory:

```
npm run lint:fix
```
8 changes: 4 additions & 4 deletions lambda/api_tokens/domain_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@


def default_expiration() -> int:
"""Calculate default token expiration (90 days from now)"""
"""Calculate default token expiration (90 days from now)."""
return now_seconds() + int(timedelta(days=90).total_seconds())


class CreateTokenAdminRequest(BaseModel):
"""Admin request to create token for a user or system"""
"""Admin request to create token for a user or system."""

tokenExpiration: int = Field(
default_factory=default_expiration, description="Unix timestamp when token expires. Defaults to 90 days"
Expand All @@ -43,7 +43,7 @@ def validate_expiration(cls, v: int) -> int:


class CreateTokenUserRequest(BaseModel):
"""User request to create their own token"""
"""User request to create their own token."""

name: str = Field(description="Human-readable name for the token")
tokenExpiration: int = Field(
Expand Down Expand Up @@ -71,7 +71,7 @@ class CreateTokenResponse(BaseModel):


class TokenInfo(BaseModel):
"""Token information (without the actual token value)"""
"""Token information (without the actual token value)."""

tokenUUID: str
tokenExpiration: int
Expand Down
4 changes: 2 additions & 2 deletions lambda/api_tokens/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ class TokenNotFoundError(Exception):


class UnauthorizedError(Exception):
"""Raised when user is not authorized to perform an action"""
"""Raised when user is not authorized to perform an action."""

pass


class ForbiddenError(Exception):
"""Raised when user lacks required permissions"""
"""Raised when user lacks required permissions."""

pass
14 changes: 7 additions & 7 deletions lambda/api_tokens/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@


class CreateTokenAdminHandler:
"""Admin creates token for any user or system"""
"""Admin creates token for any user or system."""

def __init__(self, token_table: Any) -> None:
self.token_table = token_table

def _get_user_token(self, username: str) -> dict | None:
"""Query for existing token by username using GSI"""
"""Query for existing token by username using GSI."""
response = self.token_table.query(
IndexName="username-index", KeyConditionExpression=Key("username").eq(username), Limit=1
)
Expand Down Expand Up @@ -97,13 +97,13 @@ def __call__(


class CreateTokenUserHandler:
"""User creates their own token"""
"""User creates their own token."""

def __init__(self, token_table: Any) -> None:
self.token_table = token_table

def _get_user_token(self, username: str) -> dict | None:
"""Query for existing token by username using GSI"""
"""Query for existing token by username using GSI."""
response = self.token_table.query(
IndexName="username-index", KeyConditionExpression=Key("username").eq(username), Limit=1
)
Expand Down Expand Up @@ -156,7 +156,7 @@ def __call__(


class ListTokensHandler:
"""List tokens - admins see all, users see only their own"""
"""List tokens - admins see all, users see only their own."""

def __init__(self, token_table: Any) -> None:
self.token_table = token_table
Expand Down Expand Up @@ -203,7 +203,7 @@ def __call__(self, username: str, is_admin: bool) -> ListTokensResponse:


class GetTokenHandler:
"""Get specific token details"""
"""Get specific token details."""

def __init__(self, token_table: Any) -> None:
self.token_table = token_table
Expand Down Expand Up @@ -263,7 +263,7 @@ def __call__(self, token_uuid: str, username: str, is_admin: bool) -> TokenInfo:


class DeleteTokenHandler:
"""Delete token - handles both modern and legacy tokens"""
"""Delete token - handles both modern and legacy tokens."""

def __init__(self, token_table: Any) -> None:
self.token_table = token_table
Expand Down
Loading
Loading