Skip to content

Commit 3553be7

Browse files
authored
Merge branch 'master' into chore/remove-deprecated-vw-audi
2 parents 80c9314 + 2dee05c commit 3553be7

521 files changed

Lines changed: 14572 additions & 4816 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.coderabbit.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# yaml-language-server: $schema=https://storage.googleapis.com/coderabbit_public_assets/schema.v2.json
2+
reviews:
3+
# Leave the PR description untouched (no "Summary by CodeRabbit").
4+
high_level_summary: false
5+
6+
# Suppress the walkthrough comment by disabling all its parts.
7+
changed_files_summary: false
8+
sequence_diagrams: false
9+
estimate_code_review_effort: false
10+
assess_linked_issues: false
11+
related_issues: false
12+
related_prs: false
13+
poem: false
14+
15+
# Auto-apply suggested labels and reviewers to the PR.
16+
auto_apply_labels: true
17+
auto_assign_reviewers: true
18+
19+
# Flag spam / low-quality PRs (public GitHub repos only).
20+
slop_detection:
21+
enabled: true

.github/dependabot.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,18 @@ updates:
1212
interval: "monthly"
1313
labels:
1414
- "infrastructure"
15+
- package-ecosystem: "gomod"
16+
directory: "/"
17+
schedule:
18+
interval: "monthly"
19+
# 0 disables version-update PRs; the entry still labels security updates
20+
open-pull-requests-limit: 0
21+
labels:
22+
- "infrastructure"
23+
- package-ecosystem: "npm"
24+
directory: "/"
25+
schedule:
26+
interval: "monthly"
27+
open-pull-requests-limit: 0
28+
labels:
29+
- "infrastructure"
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
name: Claude Code Review (run)
2+
3+
# Stage 2 (privileged): triggered when the "Claude Code Review" workflow above
4+
# completes. workflow_run executes in the base-repo context, so it has access
5+
# to secrets and id-token even for PRs from forks. This is what makes reviewing
6+
# external contributors' PRs possible.
7+
#
8+
# Security: the triggering workflow file is fork-controlled, so the uploaded
9+
# artifact is untrusted. We validate the PR number is purely numeric before
10+
# using it, and we only check out the base ref (never the PR head into the
11+
# workspace root) so untrusted code is never executed here. See
12+
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
13+
on:
14+
workflow_run:
15+
workflows: ["Claude Code Review"]
16+
types: [completed]
17+
18+
jobs:
19+
gate:
20+
# Only react to PR runs that finished successfully.
21+
if: >
22+
github.event.workflow_run.event == 'pull_request' &&
23+
github.event.workflow_run.conclusion == 'success'
24+
runs-on: ubuntu-latest
25+
permissions:
26+
actions: read
27+
outputs:
28+
number: ${{ steps.read.outputs.number }}
29+
found: ${{ steps.check.outputs.found }}
30+
steps:
31+
- name: Check for PR-number artifact
32+
id: check
33+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v7
34+
with:
35+
script: |
36+
const { data } = await github.rest.actions.listWorkflowRunArtifacts({
37+
owner: context.repo.owner,
38+
repo: context.repo.repo,
39+
run_id: context.payload.workflow_run.id,
40+
});
41+
core.setOutput('found', data.artifacts.some(a => a.name === 'pr-number') ? 'true' : 'false');
42+
43+
- name: Download PR number
44+
if: steps.check.outputs.found == 'true'
45+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v4
46+
with:
47+
name: pr-number
48+
run-id: ${{ github.event.workflow_run.id }}
49+
github-token: ${{ secrets.GITHUB_TOKEN }}
50+
51+
- name: Read and validate PR number
52+
id: read
53+
if: steps.check.outputs.found == 'true'
54+
run: |
55+
num="$(cat pr-number.txt)"
56+
# Artifact comes from the fork-controlled trigger workflow — never trust it blindly.
57+
if ! [[ "$num" =~ ^[0-9]+$ ]]; then
58+
echo "Refusing to proceed: PR number is not numeric ($num)" >&2
59+
exit 1
60+
fi
61+
echo "number=$num" >> "$GITHUB_OUTPUT"
62+
63+
claude-review:
64+
needs: gate
65+
if: needs.gate.outputs.found == 'true'
66+
runs-on: ubuntu-latest
67+
permissions:
68+
contents: read
69+
pull-requests: write # post the review on the PR
70+
issues: read
71+
id-token: write
72+
statuses: write # mirror the review result onto the PR head commit
73+
concurrency:
74+
group: claude-review-run-${{ needs.gate.outputs.number }}
75+
cancel-in-progress: true
76+
steps:
77+
# workflow_run runs are detached and never show up in the PR's checks, so
78+
# publish a commit status on the PR head SHA. This surfaces a "Claude Code
79+
# Review" check next to the regular CI jobs.
80+
- name: Report review pending
81+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v7
82+
with:
83+
script: |
84+
await github.rest.repos.createCommitStatus({
85+
owner: context.repo.owner,
86+
repo: context.repo.repo,
87+
sha: context.payload.workflow_run.head_sha,
88+
context: 'Claude Code Review',
89+
state: 'pending',
90+
description: 'Review in progress',
91+
target_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
92+
});
93+
94+
# Default checkout (base ref) only — do NOT check out the untrusted PR head.
95+
- name: Checkout repository
96+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
97+
with:
98+
fetch-depth: 1
99+
100+
- name: Run Claude Code Review
101+
id: review
102+
continue-on-error: true # always report status below, even on failure
103+
uses: anthropics/claude-code-action@v1
104+
with:
105+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
106+
# Provided explicitly so the review can post on fork PRs; also required
107+
# for allowed_non_write_users to take effect.
108+
github_token: ${{ secrets.GITHUB_TOKEN }}
109+
# Review PRs from external contributors who lack write access. The diff
110+
# is fetched read-only and never executed; the subprocess env is scrubbed.
111+
allowed_non_write_users: "*"
112+
# review dependency bumps opened by Dependabot
113+
allowed_bots: "dependabot[bot]"
114+
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
115+
plugins: "code-review@claude-code-plugins"
116+
prompt: "/code-review:code-review ${{ github.repository }}/pull/${{ needs.gate.outputs.number }}"
117+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
118+
# or https://code.claude.com/docs/en/cli-reference for available options
119+
120+
- name: Report review result
121+
if: always()
122+
env:
123+
OUTCOME: ${{ steps.review.outcome }}
124+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v7
125+
with:
126+
script: |
127+
const ok = process.env.OUTCOME === 'success';
128+
await github.rest.repos.createCommitStatus({
129+
owner: context.repo.owner,
130+
repo: context.repo.repo,
131+
sha: context.payload.workflow_run.head_sha,
132+
context: 'Claude Code Review',
133+
state: ok ? 'success' : 'failure',
134+
description: ok ? 'Review complete' : 'Review failed',
135+
target_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
136+
});
137+
if (!ok) core.setFailed('Claude Code Review failed');
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Claude Code Review
2+
3+
# Stage 1 (unprivileged): runs on every PR, including forks. Fork PRs get a
4+
# read-only token and no secrets, so the review itself cannot run here. This
5+
# job only records the PR number; the privileged "Claude Code Review (run)"
6+
# workflow picks it up via workflow_run and performs the actual review.
7+
on:
8+
pull_request:
9+
types: [opened, synchronize, ready_for_review, reopened]
10+
11+
concurrency:
12+
group: claude-review-${{ github.event.pull_request.number }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
prepare:
17+
# Skip draft PRs
18+
if: github.event.pull_request.draft == false
19+
runs-on: ubuntu-latest
20+
permissions: {}
21+
steps:
22+
- name: Save PR number
23+
env:
24+
PR_NUMBER: ${{ github.event.pull_request.number }}
25+
run: echo "$PR_NUMBER" > pr-number.txt
26+
27+
- name: Upload PR number
28+
uses: actions/upload-artifact@v4
29+
with:
30+
name: pr-number
31+
path: pr-number.txt
32+
retention-days: 1

.github/workflows/claude.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Claude Code
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
issues:
9+
types: [opened, assigned]
10+
pull_request_review:
11+
types: [submitted]
12+
13+
jobs:
14+
claude:
15+
if: |
16+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
pull-requests: read
24+
issues: read
25+
id-token: write
26+
actions: read # Required for Claude to read CI results on PRs
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
with:
31+
fetch-depth: 1
32+
33+
- name: Run Claude Code
34+
id: claude
35+
uses: anthropics/claude-code-action@v1
36+
with:
37+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38+
39+
# This is an optional setting that allows Claude to read CI results on PRs
40+
additional_permissions: |
41+
actions: read
42+
43+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44+
# prompt: 'Update the pull request description to include a summary of changes.'
45+
46+
# Optional: Add claude_args to customize behavior and configuration
47+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48+
# or https://code.claude.com/docs/en/cli-reference for available options
49+
# claude_args: '--allowed-tools Bash(gh pr *)'
50+

.github/workflows/triage-agent.lock.yml

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ testdata/**/*
1818
!assets/js/**/*.yaml
1919
!package*.json
2020
!evcc.dist.yaml
21+
!.coderabbit.yaml
2122
!tests/**/*.evcc.yaml
2223
!tests/**/*.tpl.yaml
2324
!tsconfig.json

AGENTS.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
3333
| [Core Domain](docs/agents/core-domain.md) | Control loop, loadpoint logic, PV surplus, charge modes, tariffs, interfaces |
3434
| [Hardware Integrations](docs/agents/hardware-integrations.md) | Charger/meter/vehicle implementations, adding new devices |
3535
| [Easee Architecture](docs/agents/easee-architecture.md) | Easee charger (REST+SignalR, async correlation, concurrency) |
36+
| [OCPP Forwarder](docs/agents/ocpp-forwarder.md) | OCPP proxy/forwarder (sidecar relay to upstream OCPP server, read-only mode) |
3637
| [Plugin System](docs/agents/plugin-system.md) | Plugin layer (HTTP, MQTT, Modbus, SunSpec, JS) |
3738
| [Web UI & API](docs/agents/web-ui-api.md) | REST API, WebSocket, Vue frontend, authentication |
39+
| [API Security](docs/agents/api-security.md) | Auth modes, JWT/API key/session, two-tier checks, credential storage |
3840

3941
### Loading guide by task type
4042

@@ -44,6 +46,7 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
4446
- **Vehicle implementation** — hardware-integrations
4547
- **UI/frontend work** — web-ui-api
4648
- **API endpoint work** — web-ui-api + core-domain
49+
- **Auth / login / API key / permissions** — api-security + web-ui-api
4750
- **Config/template work** — plugin-system
4851
- **Control loop / charging logic** — core-domain
4952
- **Bug in any area** — core-domain + relevant topic file(s)
@@ -87,7 +90,9 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
8790

8891
- No em dashes (—) in comments, commit messages, or docs. Use periods, commas, or colons
8992
- Project name is `evcc`, always lowercase
93+
- In user-facing strings, only mention `evcc` when needed to understand the context. Inside evcc's own UI the self-reference is usually redundant
9094
- Acronyms uppercase in prose: OCPP, MQTT, HEMS, SoC
95+
- Terminology: German "Phasensaldierung" (meter netting signed power across phases each instant) is "summative energy measurement" in English. Avoid "phase balancing" (means load balancing) and "net metering" (a billing scheme)
9196
- Commit subjects: `Component: short description`, no trailing period. Sub-scope in parens: `Meter (Home Assistant): ...`. Use `chore:`/`fix:`/`docs:` only for non-feature changes
9297

9398
## Comment Style
@@ -108,6 +113,7 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
108113
- Use `context.Context` for I/O, long-running, or cancelable operations
109114
- Organize code into logical packages with clear responsibilities
110115
- Prefer composition over inheritance, minimize external dependencies
116+
- Navigate Go symbols with go-to-definition and find-references rather than text search; reserve text search for comments and string literals
111117

112118
### File Patterns
113119

@@ -170,6 +176,7 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
170176

171177
### State Management
172178

179+
- Never access the store from sub-components; keep them stateless and pass the values they need as props (emit events back to the parent). Only top-level views read from the store. This keeps components reusable and testable (e.g. Storybook should never mock the store).
173180
- Use `reactive()` from Vue for simple global state
174181
- Implement property setters for nested object updates using helper functions
175182
- Use localStorage with reactive wrappers for persistent settings
@@ -250,7 +257,9 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
250257
- Use `expectModalVisible()` and `expectModalHidden()` helpers
251258
- Test configuration persistence across application restarts
252259
- Standard structure: import `{ start, stop, baseUrl }` from `./evcc`, use `test.afterEach(stop)`
253-
- Never use fixed timeouts, use existance of elements or wait for network idle
260+
- Never use fixed timeouts. Wait on element state (visibility, count, value) instead.
261+
- Never use `page.waitForLoadState("networkidle")`. SPAs keep emitting requests (websockets, polling), so it either races or hangs. Wait for the specific element / value you need instead.
262+
- Keep test names and describe titles short and concrete. They should complement each other, not repeat. Prefer `describe("aux meter") test("create")` over `describe("aux meter") test("create aux meter and verify it appears")`. Drop scenario filler like "and lands in section", "appears correctly", "ensure".
254263

255264
## Device Integration & Configuration
256265

@@ -259,8 +268,10 @@ Deep documentation on specific subsystems is available in `docs/agents/`. Load w
259268
- Device types: chargers, meters, vehicles, tariffs
260269
- Plugin protocols: Modbus, HTTP, MQTT, JavaScript, Go
261270
- Define device capabilities and configuration in templates at `templates/definition/[type]/`
271+
- Don't restate param properties that `util/templates/defaults.yaml` already defines for that param name. Properties (description, help, type, unit, default, example, required, advanced, mask, private, usages, …) are inherited from defaults; only specify a property in a template to give it a *different* value. Restating the same value is redundant duplication: reference the param by `name` alone.
262272
- Test templates: `evcc --template-type [type] --template [file]`
263273
- Update docs after template changes: `make docs`
274+
- When implementing or debugging against a third-party device library (eebus-go/ship/spine-go, ocpp-go, modbus/SunSpec), consult the library's current upstream documentation before coding rather than relying on recalled API details
264275

265276
### Configuration
266277

0 commit comments

Comments
 (0)