Skip to content

Commit f0bfe30

Browse files
Pigbibicodex
andcommitted
fix: preserve scheduler least privilege for IBKR evidence
Co-Authored-By: Codex <noreply@openai.com>
1 parent 1de4ec1 commit f0bfe30

3 files changed

Lines changed: 19 additions & 8 deletions

File tree

.github/workflows/collect-reconciliation-evidence.yml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
collect:
3535
name: Read ${{ matrix.profile }} baseline evidence
3636
runs-on: ubuntu-latest
37-
timeout-minutes: 10
37+
timeout-minutes: 15
3838
strategy:
3939
fail-fast: false
4040
matrix:
@@ -83,7 +83,7 @@ jobs:
8383
test -n "$service_url"
8484
echo "service_url=$service_url" >> "$GITHUB_OUTPUT"
8585
86-
- name: Create and run internal reconciliation request
86+
- name: Schedule one-shot internal reconciliation request
8787
id: scheduler
8888
if: ${{ steps.selection.outputs.selected == 'true' }}
8989
env:
@@ -94,14 +94,25 @@ jobs:
9494
test -n "$SERVICE_URL"
9595
job_name="ibkr-reconcile-${PROFILE}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
9696
requested_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
97+
case "$PROFILE" in
98+
soxl_soxx_trend_income) delay_minutes=3 ;;
99+
tqqq_growth_income) delay_minutes=5 ;;
100+
global_etf_rotation) delay_minutes=7 ;;
101+
russell_top50_leader_rotation) delay_minutes=9 ;;
102+
*)
103+
echo "Unsupported reconciliation profile: $PROFILE" >&2
104+
exit 1
105+
;;
106+
esac
107+
schedule="$(date -u -d "+${delay_minutes} minutes" '+%M %H %d %m *')"
97108
if gcloud scheduler jobs describe "$job_name" --project "$GCP_PROJECT_ID" --location "$GCP_REGION" >/dev/null 2>&1; then
98109
echo "Refusing to replace an existing reconciliation job: $job_name" >&2
99110
exit 1
100111
fi
101112
gcloud scheduler jobs create http "$job_name" \
102113
--project "$GCP_PROJECT_ID" \
103114
--location "$GCP_REGION" \
104-
--schedule '0 0 1 1 *' \
115+
--schedule "$schedule" \
105116
--time-zone 'Etc/UTC' \
106117
--uri "${SERVICE_URL}/reconcile" \
107118
--http-method POST \
@@ -113,7 +124,6 @@ jobs:
113124
echo "job_name=$job_name"
114125
echo "requested_at=$requested_at"
115126
} >> "$GITHUB_OUTPUT"
116-
gcloud scheduler jobs run "$job_name" --project "$GCP_PROJECT_ID" --location "$GCP_REGION"
117127
118128
- name: Read private no-order reconciliation candidate
119129
if: ${{ steps.selection.outputs.selected == 'true' }}
@@ -128,7 +138,7 @@ jobs:
128138
test -n "$REQUESTED_AT"
129139
mkdir -p reports
130140
report_uri=''
131-
for attempt in $(seq 1 60); do
141+
for attempt in $(seq 1 96); do
132142
report_uri="$(gcloud logging read "resource.type=\"cloud_run_revision\" AND resource.labels.service_name=\"${SERVICE}\" AND timestamp>=\"${REQUESTED_AT}\" AND textPayload:\"execution_report gs://\"" --project "$GCP_PROJECT_ID" --freshness=15m --limit=10 --format='value(textPayload)' 2>/dev/null | awk '$1 == "execution_report" {print $2; exit}')"
133143
if [ -n "$report_uri" ]; then
134144
break

docs/ibkr_reconciliation_baseline_enrollment.zh-CN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ URI、部署 Cloud Run、连接券商或提交订单。实际启用仍需要单
9191
## 收集两份候选收据
9292

9393
`Collect IBKR Reconciliation Evidence` 是显式手动工作流。由于这些 Cloud Run 服务只接受
94-
内部入口,工作流会以部署身份创建一个名称绑定到本次运行的**一次性** Cloud Scheduler
95-
任务,再由既有的最小权限 Scheduler 身份调用冻结服务的 `POST /reconcile`。它随后只从
94+
内部入口,工作流会以部署身份创建一个名称绑定到本次运行、几分钟后只执行一次的 Cloud
95+
Scheduler 任务,再由既有的最小权限 Scheduler 身份调用冻结服务的 `POST /reconcile`。它随后只从
9696
私有运行报告提取脱敏 `ibkr_reconciliation_candidate.v1`,在 30 天内保留 artifact,并在
9797
成功或失败时删除该一次性任务。它不调用 `/run`、不修改 GitHub 变量、不发布状态账本,也
9898
不发送任何订单。

tests/test_reconciliation_evidence_workflow.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ def test_reconciliation_evidence_uses_internal_one_shot_scheduler_and_cleans_up(
1414

1515
assert '"${SERVICE_URL}/reconcile"' in workflow
1616
assert "gcloud scheduler jobs create http" in workflow
17-
assert "gcloud scheduler jobs run" in workflow
17+
assert 'schedule="$(date -u -d "+${delay_minutes} minutes"' in workflow
1818
assert "gcloud scheduler jobs delete" in workflow
1919
assert "gcloud storage cat \"$report_uri\"" in workflow
20+
assert "gcloud scheduler jobs run" not in workflow
2021
assert "/run" not in workflow
2122
assert "curl " not in workflow

0 commit comments

Comments
 (0)