@bivy/bivy 0.12.0-staging.404 → 0.12.0-staging.406
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.js +43 -9
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -2878,6 +2878,17 @@ const RELAY_COMMANDS = {
|
|
|
2878
2878
|
});
|
|
2879
2879
|
return;
|
|
2880
2880
|
}
|
|
2881
|
+
const remoteSessionRequestId = requestId ?? randomUUID();
|
|
2882
|
+
const sessionAdmission = await admitRelaySessionCreate(remoteSessionRequestId);
|
|
2883
|
+
if (!sessionAdmission.allowed) {
|
|
2884
|
+
relay?.sendEvent({
|
|
2885
|
+
type: "session.error",
|
|
2886
|
+
code: sessionAdmission.code || "remote_session_limit",
|
|
2887
|
+
error: sessionAdmission.error,
|
|
2888
|
+
requestId,
|
|
2889
|
+
});
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2881
2892
|
let record;
|
|
2882
2893
|
try {
|
|
2883
2894
|
// Deduped by requestId so a client's post-reconnect retry adopts the
|
|
@@ -3131,6 +3142,24 @@ async function modelAuthFetch(pathname, init = {}) {
|
|
|
3131
3142
|
headers.set("content-type", "application/json");
|
|
3132
3143
|
return fetch(`${sessionAdvertiseTarget.controlPlaneUrl.replace(/\/$/, "")}${pathname}`, { ...init, headers });
|
|
3133
3144
|
}
|
|
3145
|
+
async function admitRelaySessionCreate(idempotencyKey) {
|
|
3146
|
+
// Self-hosted/direct deployments without an account extension stay unrestricted:
|
|
3147
|
+
// the control plane answers allowed when no deployment extension is configured.
|
|
3148
|
+
const res = await modelAuthFetch("/node/policy/check", {
|
|
3149
|
+
method: "POST",
|
|
3150
|
+
body: JSON.stringify({ operation: "session.create", idempotencyKey }),
|
|
3151
|
+
});
|
|
3152
|
+
if (!res)
|
|
3153
|
+
return { allowed: true };
|
|
3154
|
+
const decision = await res.json().catch(() => ({}));
|
|
3155
|
+
if (res.ok && decision.allowed !== false)
|
|
3156
|
+
return { allowed: true };
|
|
3157
|
+
return {
|
|
3158
|
+
allowed: false,
|
|
3159
|
+
code: decision.code,
|
|
3160
|
+
error: decision.reason || decision.error || "This account has reached its remote session allowance.",
|
|
3161
|
+
};
|
|
3162
|
+
}
|
|
3134
3163
|
// Debounced model-auth sync trigger. A relay wake (`work.available`) fires this
|
|
3135
3164
|
// so peers answer a new node's vault-key request promptly (event-driven) instead
|
|
3136
3165
|
// of on the steady 30s poll. Coalesces a burst of wakes into one sync.
|
|
@@ -4596,18 +4625,23 @@ function invalidateGitHubApps() {
|
|
|
4596
4625
|
// token nor an app key. When BIVY_HOSTED_MINT is set they mint a fresh,
|
|
4597
4626
|
// short-lived token from the control plane per git op — cached until ~5 min
|
|
4598
4627
|
// before expiry so a burst of git ops is a single round trip. This is the final
|
|
4599
|
-
// fallback rung after local apps and BIVY_GITHUB_TOKEN.
|
|
4600
|
-
|
|
4601
|
-
|
|
4628
|
+
// fallback rung after local apps and BIVY_GITHUB_TOKEN. Passing the repo lets
|
|
4629
|
+
// the control plane pick the matching central-app installation and scope the
|
|
4630
|
+
// token down to that repo, so the cache is keyed per repo.
|
|
4631
|
+
const hostedMintCache = new Map();
|
|
4632
|
+
async function hostedMintToken(repo) {
|
|
4602
4633
|
if (!process.env.BIVY_HOSTED_MINT || !sessionAdvertiseTarget)
|
|
4603
4634
|
return undefined;
|
|
4635
|
+
const cacheKey = repo ?? "";
|
|
4604
4636
|
const now = Date.now();
|
|
4605
|
-
|
|
4606
|
-
|
|
4637
|
+
const cached = hostedMintCache.get(cacheKey);
|
|
4638
|
+
if (cached && cached.expiresAt - now > 5 * 60 * 1000)
|
|
4639
|
+
return cached.token;
|
|
4607
4640
|
try {
|
|
4608
4641
|
const res = await fetch(`${sessionAdvertiseTarget.controlPlaneUrl.replace(/\/$/, "")}/node/hosted-git-credential`, {
|
|
4609
4642
|
method: "POST",
|
|
4610
|
-
headers: { authorization: `Bearer ${sessionAdvertiseTarget.enrollmentToken}
|
|
4643
|
+
headers: { authorization: `Bearer ${sessionAdvertiseTarget.enrollmentToken}`, "content-type": "application/json" },
|
|
4644
|
+
body: JSON.stringify(repo ? { repo } : {}),
|
|
4611
4645
|
});
|
|
4612
4646
|
if (!res.ok)
|
|
4613
4647
|
return undefined;
|
|
@@ -4615,7 +4649,7 @@ async function hostedMintToken() {
|
|
|
4615
4649
|
if (!data.token)
|
|
4616
4650
|
return undefined;
|
|
4617
4651
|
const parsed = data.expiresAt ? Date.parse(data.expiresAt) : NaN;
|
|
4618
|
-
hostedMintCache
|
|
4652
|
+
hostedMintCache.set(cacheKey, { token: data.token, expiresAt: Number.isFinite(parsed) ? parsed : now + 55 * 60 * 1000 });
|
|
4619
4653
|
return data.token;
|
|
4620
4654
|
}
|
|
4621
4655
|
catch {
|
|
@@ -4639,7 +4673,7 @@ async function resolveTokenForWorkItem(item) {
|
|
|
4639
4673
|
}
|
|
4640
4674
|
}
|
|
4641
4675
|
}
|
|
4642
|
-
return (await resolveGitHubToken()) ?? (await hostedMintToken());
|
|
4676
|
+
return (await resolveGitHubToken()) ?? (await hostedMintToken(item.repo));
|
|
4643
4677
|
}
|
|
4644
4678
|
/**
|
|
4645
4679
|
* The token for interactive repo operations (clone/fetch/push/PR) on `owner/repo`.
|
|
@@ -4687,7 +4721,7 @@ async function resolveTokenForRepo(owner, repo) {
|
|
|
4687
4721
|
}
|
|
4688
4722
|
}
|
|
4689
4723
|
}
|
|
4690
|
-
return (await resolveGitHubToken()) ?? (await hostedMintToken());
|
|
4724
|
+
return (await resolveGitHubToken()) ?? (await hostedMintToken(`${owner}/${repo}`));
|
|
4691
4725
|
}
|
|
4692
4726
|
/** The session source a Linear-issue pickup advertises, keyed by the issue's
|
|
4693
4727
|
* provider-native id so the control plane can correlate a re-dispatch to it
|
package/package.json
CHANGED