Skip to content
Merged
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
30 changes: 27 additions & 3 deletions .downstream/native-domains.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ OAuth-like accounts can be selected; the source and target lists are disjoint.
The extension never rewrites account model mappings, proxies, WS switches,
groups, quota or scheduling state. Normal credential refresh remains available.

The protocol reference is ranxi v2.10.3 (`fd1b5ee4`), non-rotating branch.
The protocol reference is ranxi v2.10.5 (`d977e7a5`), non-rotating branch.
Candidates are stored per source with an active-source preference. Their maximum
lease is 230 seconds, capped by earlier upstream expiry; seeing a value again
while its lease is live does not extend it. Source acquisition uses the normal
Expand All @@ -111,6 +111,16 @@ headers, and generate a new legacy `session_id` per shot. The second shot carrie
only the first probe's STATE and target `__cflb` with the same borrowed `__oailb`.
Nothing is written back to the business session. The business request keeps its
own model, tier, cookies, STATE and history; borrowing replaces only `__oailb`.
Native HTTP business STATE echo follows the original provenance rule: unknown or expired
process-local provenance preserves the caller's STATE; a live foreign-account
record strips it. This does not relax two-shot target qualification or the
existing WS/WS-to-HTTP bridge provenance requirements.

Observations report their connect/TLS/write/header phase and attempt count.
They may retry once only with transport trace proving a connection failure before
HTTP request headers were written. Unobserved errors, responses, written headers,
cancellation or an exhausted diagnostic budget forbid retry. Ordinary business
generations retain their existing retry policy.

The original cache identity includes route cookie, proxy, Authorization,
ChatGPT-Account-ID, UA, Originator, Version, business STATE and TLS profile.
Expand Down Expand Up @@ -213,10 +223,24 @@ candidate owner. `probe_context.subject_role` distinguishes source self-checks
from target checks. Self-check results do not qualify business traffic or mutate
the source's health/status.

Ranxi reference: v2.10.3 (`fd1b5ee4eeb20961fbb783fa6f136a1704271e90`). Its
Administrator `scenario: codex_replay` accepts explicit HTTP `mode: ordinary` or
`borrowed` and `replay: {body, headers}` for controlled task/tool comparisons.
The JSON body is limited to 1 MiB, must select the requested model, stream with
`store: false`, use complete history without `previous_response_id`, and carry a
`codex-acceptance-` session in both prompt-cache and native session/thread headers.
Only native client identity/metadata/STATE headers are accepted; auth, cookies,
URL overrides and duplicate fields are rejected. The ordinary source control
must use a saved source and configured model; borrowing still requires a saved
target. Each call retains the eight-physical-attempt cap and a five-minute
generation budget. Results return actual business `turn_state` for the next
isolated replay turn; probe STATE is never returned or copied. The controller
executes synthetic tools locally and preserves full-history items, rather than
inventing tool results or executing model code in the production service.

Ranxi reference: v2.10.5 (`d977e7a5e24e5536db6ce8b8478743e0c4b11f77`). Its
fingerprint, gateway-cookie, target-probe and automatic-setup core files are
unchanged from v2.10.2. The scoped update and retained host adaptations are
listed in [the review](upstream-review-ranxi-v2.10.3.md). OAuth search-history compatibility
listed in [the review](upstream-review-ranxi-v2.10.5.md). OAuth search-history compatibility
is supplied by the official v0.2.15 integration. Automatic group membership,
Mihomo exit rotation and removal of harvesting attempt/concurrency bounds are
not adopted; existing account mappings, network routes and protocol switches stay
Expand Down
82 changes: 82 additions & 0 deletions .downstream/ranxi-borrow-reference.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"repository": "ranxi2001/sub2api",
"tag": "v2.10.5",
"commit": "d977e7a5e24e5536db6ce8b8478743e0c4b11f77",
"adaptations": [
"Test-only identifier prefix; original function bodies.",
"Host HTTPUpstream, TLS profile, context markers, turn-state extractor and error display helpers.",
"Route container retains only cookie/expires; unused Mihomo/proxy fields are omitted.",
"Source payload calls the original Pelican builder with Astra, OAuth, fixed prompt and medium effort."
],
"files": {
"backend/internal/service/openai_codex_turn_state.go": {
"sha256": "d5c7720ad556e68bd4505c6dcec009d8489141e5bd4b6c7984d45a38430c7440",
"declarations": {
"guardOpenAICodexTurnStateEcho": "5ce7aabcb3057409d9b746c333a14b70823e0847299f8836c6a9a5d342b938c2"
}
},
"backend/internal/service/openai_codex_state_probe.go": {
"sha256": "ee7de916510cf6d48c94a542c731aa52fd7c4b0e8dc410b0d217229df05e99ba",
"declarations": {
"runOpenAICodexStateProbe": "eccfd327d172e198d947dcead28d77a5921e60a90c2e00e5660f56ded41a86c6",
"ProbeOpenAICodexStateRoute": "13e1cf1f0d8492d65aced50bec502350506da3c0986f56091bafda9162d15ec1",
"fail": "de12462962b42aab47fef6c33329d80648f6089388f1159d69ad5629964a1897",
"shotUsable": "9e74562f9555a5cfa40fd8c6237191ea0c2507577af5ebdf0a69f3c3507a04b4",
"openAICodexStateVerdictReason": "936f726961005cc672e1e30ab293c92f4f00f29b87c4bb103f1b6202c00f62f1",
"fireOpenAICodexStateShotRequest": "9b3b1c7cfd29e9274ed3e28034e2abd1e39ab6c7d93eec13eca2d31eb19b6256",
"openAICodexStateRouteCookies": "f1c37c5f2411b18b2e1ad72b8cf68fa5e6e25c31bbb3cbcd4f77ba633e7ae68b",
"openAICodexStateDetail": "b35df3e1ee98dfb8ad423a8f37826e5ee4ec971b3329f338d3b62617f9bd70c4",
"openAICodexStateStreamEvents": "734c354320e4a9fe9debb331cafb747040de4e7b9c53c113357eaf9a86036107",
"openAICodexStateStreamModel": "6e6e64daea561c6ef38f52472f105b4670caab7de3a2bfe039751d3126df4e44",
"openAICodexStateStreamErrorPayload": "76abf87c7a62cd22398fa7779e15bcf140a2850b26a5d507c92a07f43dea1496"
}
},
"backend/internal/service/openai_codex_probe_response.go": {
"sha256": "cff3af2e6c01bbc7308ec8a4f9ea4596ebfd96689e38e03ef09761c9b2eb6a88",
"declarations": {
"validateCodexProbeResponse": "43b9a73bf19ca3fd04c42f85150459dfd5d3823b8f963463cdc06d1726c4daea"
}
},
"backend/internal/service/openai_codex_ws_anchor.go": {
"sha256": "b5a3100719948d0f6c5f6a4052f7bbb70d668eaa3ce4e4480d2edd3706adabb5",
"declarations": {
"replaceCodexWSAnchorCookie": "ee9b8934f40b8a0d33b9ced3e716bd21d2cdb81bae4e345c69782231d0269f3f"
}
},
"backend/internal/service/openai_codex_ticket.go": {
"sha256": "186ea9b390324b58613948a1371944a0eb6b6457c3aa52ff6f24fddb35d59831",
"declarations": {
"jsonString": "d595eca92f7086de35294d4fc27edf07df49d70b057642fe77c2510e909ee311",
"normalizeOpenAICodexTicketModel": "8b4bf5d56064064308040b1a1eda56b220e76f2cf078a59c6042b48a3b940b70"
}
},
"backend/internal/repository/codex_gateway_pin.go": {
"sha256": "e9f6eb813a440282c9d39ab5d4e03a96f8862438bcfd143fa61c1ac23513bdfb",
"declarations": {
"codexGatewayCookiePathMatches": "91628f271432d6fb6426783b670e1ed08f7c72811565963d2f13255e840958bc",
"codexGatewayRouteFromResponse": "31a7c69a8a39c482f01be40b3b6909b07140400f5893cd990890346087e60d85"
}
},
"backend/internal/service/account_test_service.go": {
"sha256": "6c90400653ac6ab22987cb717db235530a353af4dc0e00ed35fd77f876283fcd",
"declarations": {
"createOpenAITestPayload": "35451845d4ae6c6b373ec9afe050fd2606f73f7fecef795662eb3cba2e94fe86"
}
},
"backend/internal/service/pelican_test_service.go": {
"sha256": "a601a52aae9ccef507d90b7faa1f1cc029e9e907af735e949a236883f87bf4ee",
"declarations": {
"createPelicanOpenAIPayload": "56e2c4d395beefb8f564d331ffe2afc98ed4018c1ca1ab33ab9917f07cdf0a55",
"promptOrDefault": "b807f11ad9bc4f9e6d90d6df9bb2b1a60024731553893041ad9b87f6866acdcd",
"normalizePelicanReasoningEffort": "50d726f8594b9f5ad0dcf95921b46b73ab4a8e7078873d3281352d46b5ce6934"
}
}
},
"generated_sha256": "9ad61fb4b2a7d3230f374568ba6145635a8434579763492b292ee0ce345c1f48",
"reviewed_host_policies": {
"backend/internal/repository/astra_target_validation.go": "420b9a2f631ae382ee5455aa922b71bdde413bfbe3ea25b048d8fc0d55f9f1d5",
"backend/internal/repository/astra_routing_upstream.go": "3969048bfe953dbded5a686378eb88be52b685cfb208f9f0a97a10c52f337b13",
"backend/internal/service/astra_automatic_setup.go": "c60fc40730d667ae5b8f55d6084c9961073a107fe7ba40e68d577f722389874f",
"backend/internal/service/openai_codex_fingerprint.go": "c974262d3b0fff3c8d1eb8286078234be2905b2402245f4a46b4e9bced63eeb9"
}
}
50 changes: 50 additions & 0 deletions .downstream/upstream-review-ranxi-v2.10.5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# ranxi v2.10.5 borrowing review

Reference: `d977e7a5e24e5536db6ce8b8478743e0c4b11f77`, released v2.10.5.
Official Wei-Shaw v0.2.15 remains the downstream base. This is a scoped update,
not a merge of ranxi's database, BPS, scheduling, or exit-management features.

## Protocol evidence

`.github/scripts/generate_ranxi_borrow_reference.py` extracts original functions
from the pinned Git object, prefixes test-only identifiers, and records source
and generated hashes in `ranxi-borrow-reference.json`. It does not translate the
reference algorithm. `--check` verifies provenance offline when that Git object
is available. The generated Go file is test-only and needs no network in CI.

The differential test covers the original source payload, two-shot target
requests and verdicts, cookie scope/deletion/expiry, and business STATE echo.
Host-dependent preparation, fingerprint and cache policies have source hashes
and retain the previously reviewed account coordination and observation adapters.
These hashes are a review boundary, not a claim that those whole subsystems were
executed as a second reference service.

The source/pool/probe core is unchanged from v2.10.3. Sol remains an independent
downstream extension; an Astra result never qualifies Sol.

## Changes

- Restore original native HTTP business STATE echo behavior: unknown or expired local
provenance is preserved; a live record identifying a different account still
strips it. Target two-shot qualification and WS provenance are unchanged.
- Observe connect/TLS/write/header phases. Retry an observation once only when
transport trace proves failure before any HTTP request headers were written.
No trace, any response, cancellation, exhausted diagnostic budget, or written
headers forbids replay. Every connection attempt counts against the budget.
- Port account-test SSE keepalive from #350, preserving the host parser's error
wording, observation cancellation and already committed successful terminals.
Body-close cancellation after completion must not erase a completed test.
A heartbeat is not model output.
- Extend the existing administrator diagnostic with an explicitly selected,
bounded native replay for comparable fixture/tool sessions. Ordinary source
controls are limited to saved source accounts. No credentials, routing cookies,
destination override or previous-response anchor can be supplied by replay.

The production account-proxy selection and live model results are deployment
evidence, not protocol unit-test results. No recurring ranxi update is installed.

## Excluded release changes

BPS credentials/Redis/tool routing, optional timezone rewriting, subscription
renewal, Grok video, automatic grouping and Mihomo rotation are outside this fix.
The existing WS switch and official upstream synchronization remain unchanged.
123 changes: 123 additions & 0 deletions .github/scripts/generate_ranxi_borrow_reference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env python3
"""Extract pinned upstream declarations; no hand-translated reference algorithm.

Run from the repository root. --check validates the committed generated file and
manifest against Git objects, without network access or rewriting files.
"""
import argparse
import hashlib
import json
from pathlib import Path
import re
import subprocess

REVISION = 'd977e7a5e24e5536db6ce8b8478743e0c4b11f77'
ROOT = Path(__file__).resolve().parents[2]
OUTPUT = ROOT / 'backend/internal/service/codex_gateway_borrow_ranxi_generated_test.go'
MANIFEST = ROOT / '.downstream/ranxi-borrow-reference.json'
FILES = {
'backend/internal/service/openai_codex_turn_state.go': ['guardOpenAICodexTurnStateEcho'],
'backend/internal/service/openai_codex_state_probe.go': [
'runOpenAICodexStateProbe', 'ProbeOpenAICodexStateRoute', 'fail',
'shotUsable', 'openAICodexStateVerdictReason',
'fireOpenAICodexStateShotRequest', 'openAICodexStateRouteCookies',
'openAICodexStateDetail', 'openAICodexStateStreamEvents',
'openAICodexStateStreamModel', 'openAICodexStateStreamErrorPayload'],
'backend/internal/service/openai_codex_probe_response.go': ['validateCodexProbeResponse'],
'backend/internal/service/openai_codex_ws_anchor.go': ['replaceCodexWSAnchorCookie'],
'backend/internal/service/openai_codex_ticket.go': ['jsonString', 'normalizeOpenAICodexTicketModel'],
'backend/internal/repository/codex_gateway_pin.go': ['codexGatewayCookiePathMatches', 'codexGatewayRouteFromResponse'],
'backend/internal/service/account_test_service.go': ['createOpenAITestPayload'],
'backend/internal/service/pelican_test_service.go': ['createPelicanOpenAIPayload', 'promptOrDefault', 'normalizePelicanReasoningEffort'],
}

def read(path):
return subprocess.check_output(['git', 'show', f'{REVISION}:{path}'], cwd=ROOT)

def extract(source, name):
pattern = r'(?m)^func (?:\([^\n]*\) )?' + re.escape(name) + r'\([^\n]*'
start = re.search(pattern, source)
if not start:
raise ValueError('missing declaration: ' + name)
end = re.search(r'(?m)^}', source[start.start():])
if not end:
raise ValueError('unterminated declaration: ' + name)
return source[start.start():start.start() + end.end()] + '\n'

def generate():
manifest = {'repository': 'ranxi2001/sub2api', 'tag': 'v2.10.5', 'commit': REVISION,
'adaptations': ['Test-only identifier prefix; original function bodies.',
'Host HTTPUpstream, TLS profile, context markers, turn-state extractor and error display helpers.',
'Route container retains only cookie/expires; unused Mihomo/proxy fields are omitted.',
'Source payload calls the original Pelican builder with Astra, OAuth, fixed prompt and medium effort.'], 'files': {}}
parts = []
names = set()
for path, functions in FILES.items():
raw = read(path)
source = raw.decode('utf-8')
fragments = [extract(source, name) for name in functions]
names.update(functions)
if path.endswith('openai_codex_state_probe.go'):
type_names = ['OpenAICodexStateVerdict', 'OpenAICodexStateProbeResult', 'openAICodexStateShot', 'openAICodexStateProbeContextKey']
for name in type_names:
# Multi-line structs, unlike the string alias and empty key.
start = source.index('type ' + name + ' ')
line_end = source.index('\n', start)
if source[start:line_end].endswith('{'):
end = re.search(r'(?m)^}', source[line_end:])
fragment = source[start:line_end+end.end()]+'\n'
else:
fragment = source[start:line_end]+'\n'
fragments.append(fragment)
names.add(name)
for block in re.findall(r'(?m)^const \([\s\S]*?^\)', source):
fragments.append(block+'\n')
names.update(re.findall(r'(?m)^\t([A-Za-z]\w*)', block))
for name, fragment in zip(functions, fragments):
manifest['files'].setdefault(path, {'sha256': hashlib.sha256(raw).hexdigest(), 'declarations': {}})['declarations'][name] = hashlib.sha256(fragment.encode()).hexdigest()
parts.extend(fragments)
names.add('codexGatewayRoute')
combined = '\n'.join(parts)
combined = re.sub(r'\b('+'|'.join(sorted(names, key=len, reverse=True))+r')\b', lambda m: 'ranxiRef'+m[0][0].upper()+m[0][1:], combined)
header = '''// Code generated by .github/scripts/generate_ranxi_borrow_reference.py; DO NOT EDIT.
// ranxi2001/sub2api v2.10.5, LGPL-3.0, commit '''+REVISION+'''.
package service
import (
"bufio"
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/google/uuid"
"github.com/gin-gonic/gin"
"github.com/Wei-Shaw/sub2api/internal/pkg/openai"
"github.com/Wei-Shaw/sub2api/internal/pkg/tlsfingerprint"
)
type ranxiRefCodexGatewayRoute struct { cookie http.Cookie; expires time.Time }
'''
data = subprocess.run(['gofmt'], input=(header+combined).encode(), capture_output=True, check=True).stdout.replace(b'\r\n', b'\n')
manifest['generated_sha256'] = hashlib.sha256(data).hexdigest()
# Adjacent host-dependent policies are reviewed by source hash, not replaced
# with a second hand-written implementation or claimed as executed functions.
manifest['reviewed_host_policies'] = {p: hashlib.sha256(read(p)).hexdigest() for p in [
'backend/internal/repository/astra_target_validation.go',
'backend/internal/repository/astra_routing_upstream.go',
'backend/internal/service/astra_automatic_setup.go',
'backend/internal/service/openai_codex_fingerprint.go']}
return data, (json.dumps(manifest, indent=2)+'\n').encode()

if __name__ == '__main__':
parser = argparse.ArgumentParser(); parser.add_argument('--check', action='store_true')
args = parser.parse_args()
generated, manifest = generate()
if args.check:
assert OUTPUT.read_bytes().replace(b'\r\n', b'\n') == generated
assert MANIFEST.read_bytes().replace(b'\r\n', b'\n') == manifest
else:
OUTPUT.write_bytes(generated); MANIFEST.write_bytes(manifest)
print('Pinned ranxi reference '+('verified' if args.check else 'generated'))
3 changes: 3 additions & 0 deletions .github/workflows/downstream-verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ jobs:
- name: Codex preparation coordination race tests
working-directory: backend
run: go test -p=1 -race -tags unit ./internal/service -run '^TestCodexBorrow(Flight|DifferentTargets|CancelledParent|DiagnoseHTTPTerminalAndDispatchEvidence)|^TestCodexGatewayBorrowRunnerCancellationStopsQueuedAndInflightAndRetainsRawOutput$' -count=1
- name: Account test keepalive lifecycle race tests
working-directory: backend
run: go test -p=1 -race -tags unit ./internal/service -run '^TestAccountTestKeepalive' -count=1
- name: Upstream automation classifier tests
run: |
python3 .github/scripts/test_upstream_risk.py
Expand Down
Loading
Loading