fix(functions): rebuild stale dist + predeploy build hook (FUNCTIONS-DIST-STALE)
The phrase-change 🔑 alert never fired live because the deployed artifact
didn't contain it — functions/dist is committed and is what deploys, and I
changed functions/src without rebuilding it. My own gates were green and
irrelevant: tsc --noEmit emits nothing, ts-jest compiles in memory. The user
deployed twice, faithfully, and shipped my stale artifact both times. "git
status clean" is not "deployable current".
Two fixes: dist rebuilt (diff confirms exactly one stale function,
onCoupleKeyRotated — the phrase edge), and firebase.json now carries a
predeploy hook (npm run build) so every functions deploy compiles first —
the mistake class is structurally gone rather than remembered. Landmine
written up as FUNCTIONS-DIST-STALE in the manual: when verifying "is X
deployed", compare against dist/, not src/ — src is the intent, dist is
the truth.
Functions tests green (108).
This commit is contained in:
parent
65dbd1a9c9
commit
8a9bd41fe5
|
|
@ -1472,6 +1472,12 @@ OOB code = `truncate6(SHA-256(pubkey ‖ nonce))`.
|
||||||
**Fix (R30, C1)**: `GamePromptController.consumeForSession(sessionId)` is called from every game's `enter/leave` (the same `ActiveGameSessionMonitor` hook the foreground-suppression check uses), and the controller replaces stale banners on a new start (last-wins by timestamp) so a banner for a session the user is already inside is never shown.
|
**Fix (R30, C1)**: `GamePromptController.consumeForSession(sessionId)` is called from every game's `enter/leave` (the same `ActiveGameSessionMonitor` hook the foreground-suppression check uses), and the controller replaces stale banners on a new start (last-wins by timestamp) so a banner for a session the user is already inside is never shown.
|
||||||
**Re-introduction risk**: any new entry point into a game (a deep link, a partner-joined push, a "rematch?" CTA) that bypasses `ActiveGameSessionMonitor.enter` and therefore doesn't call `consumeForSession` will leave the previous banner alive - and the next push will look like a duplicate. The B6c split of `onGameSessionUpdate` into per-game part-finished triggers means a new game also needs a per-game monitor hook, not a shared one. Verified live across all four session games post-R30.
|
**Re-introduction risk**: any new entry point into a game (a deep link, a partner-joined push, a "rematch?" CTA) that bypasses `ActiveGameSessionMonitor.enter` and therefore doesn't call `consumeForSession` will leave the previous banner alive - and the next push will look like a duplicate. The B6c split of `onGameSessionUpdate` into per-game part-finished triggers means a new game also needs a per-game monitor hook, not a shared one. Verified live across all four session games post-R30.
|
||||||
|
|
||||||
|
### FUNCTIONS-DIST-STALE - editing functions/src does NOT change what deploys (fixed with a predeploy hook)
|
||||||
|
**Symptom (2026-07-16)**: a live feature test showed the deployed `onCoupleKeyRotated` lacked code that was plainly in `functions/src` and committed — the user deployed twice and both deploys shipped the old behaviour.
|
||||||
|
**Cause**: `functions/dist` (compiled JS) is COMMITTED and is what `firebase deploy` ships; nothing rebuilt it. The change's author ran `tsc --noEmit` (checks, emits nothing) and `npm test` (ts-jest, compiles in-memory) — both green, both irrelevant to the artifact. `git status` clean ≠ deployable current.
|
||||||
|
**Fix**: `firebase.json` now has `predeploy: npm --prefix $RESOURCE_DIR run build`, so every functions deploy compiles first — the mistake class is structurally gone.
|
||||||
|
**Re-introduction risk**: any committed build artifact with no build-on-deploy hook. If a second codebase/artifact is ever added, wire its predeploy the same day. And when verifying "is X deployed", compare against `dist/`, not `src/` — src is the intent, dist is the truth.
|
||||||
|
|
||||||
### FUNCTIONS-V2-DEPLOY - 2nd-gen deploys can fail mid-deploy with "Changing from HTTPS function to background triggered function" if a stray service is left behind
|
### FUNCTIONS-V2-DEPLOY - 2nd-gen deploys can fail mid-deploy with "Changing from HTTPS function to background triggered function" if a stray service is left behind
|
||||||
**Symptom (2026-07-08)**: a deploy that swapped a Cloud Function from HTTPS to Firestore-triggered (e.g. promoting a callable to a scheduled job, or splitting a function module) failed with *"Changing from an HTTPS function to a background triggered function is not allowed"*. A first-ever v2 deploy can also fail with Eventarc service-agent IAM propagation races - the *"retry in a few minutes"* failures.
|
**Symptom (2026-07-08)**: a deploy that swapped a Cloud Function from HTTPS to Firestore-triggered (e.g. promoting a callable to a scheduled job, or splitting a function module) failed with *"Changing from an HTTPS function to a background triggered function is not allowed"*. A first-ever v2 deploy can also fail with Eventarc service-agent IAM propagation races - the *"retry in a few minutes"* failures.
|
||||||
**Root cause**: an orphaned `https` service (from a partial deploy or a previous attempt) is blocking the new background trigger from being created under the same name. The 2nd-gen quota was the proximate cause of the *initial* deploy failure (Cloud Run CPU quota couldn't fit ~35 services at v2's default 1 vCPU/instance; container healthchecks failed with *"Quota exceeded for total allowable CPU per project per region"*) - `functions/src/options.ts` pins `cpu: 'gcf_gen1'`, `concurrency: 1`, `maxInstances: 5` as the workaround.
|
**Root cause**: an orphaned `https` service (from a partial deploy or a previous attempt) is blocking the new background trigger from being created under the same name. The 2nd-gen quota was the proximate cause of the *initial* deploy failure (Cloud Run CPU quota couldn't fit ~35 services at v2's default 1 vCPU/instance; container healthchecks failed with *"Quota exceeded for total allowable CPU per project per region"*) - `functions/src/options.ts` pins `cpu: 'gcf_gen1'`, `concurrency: 1`, `maxInstances: 5` as the workaround.
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,10 @@
|
||||||
".git",
|
".git",
|
||||||
"firebase-debug.log",
|
"firebase-debug.log",
|
||||||
"firebase-debug.*.log"
|
"firebase-debug.*.log"
|
||||||
|
],
|
||||||
|
"predeploy": [
|
||||||
|
"npm --prefix \"$RESOURCE_DIR\" run build"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.onCoupleKeyRotated = void 0;
|
exports.onCoupleKeyRotated = void 0;
|
||||||
exports.isKeyGenerationIncrease = isKeyGenerationIncrease;
|
exports.isKeyGenerationIncrease = isKeyGenerationIncrease;
|
||||||
|
exports.isPhrasePublished = isPhrasePublished;
|
||||||
const admin = __importStar(require("firebase-admin"));
|
const admin = __importStar(require("firebase-admin"));
|
||||||
const firestore_1 = require("firebase-functions/v2/firestore");
|
const firestore_1 = require("firebase-functions/v2/firestore");
|
||||||
const queueAndPush_1 = require("../notifications/queueAndPush");
|
const queueAndPush_1 = require("../notifications/queueAndPush");
|
||||||
|
|
@ -55,26 +56,51 @@ function isKeyGenerationIncrease(before, after) {
|
||||||
const a = typeof after === 'number' ? after : 0;
|
const a = typeof after === 'number' ? after : 0;
|
||||||
return a > b;
|
return a > b;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Pure edge guard for a newly PUBLISHED recovery phrase (phase 1 of the change handshake).
|
||||||
|
*
|
||||||
|
* Deliberately keyed on `phraseGeneration`, not `phraseWrapGeneration`: the publish is the moment the
|
||||||
|
* partner needs to act on, and their ack is what lets the change finish at all. Same shape as
|
||||||
|
* isKeyGenerationIncrease so the two read alike.
|
||||||
|
*/
|
||||||
|
function isPhrasePublished(before, after) {
|
||||||
|
const b = typeof before === 'number' ? before : 0;
|
||||||
|
const a = typeof after === 'number' ? after : 0;
|
||||||
|
return a > b;
|
||||||
|
}
|
||||||
exports.onCoupleKeyRotated = (0, firestore_1.onDocumentUpdated)('couples/{coupleId}', async (event) => {
|
exports.onCoupleKeyRotated = (0, firestore_1.onDocumentUpdated)('couples/{coupleId}', async (event) => {
|
||||||
var _a, _b, _c;
|
var _a, _b, _c;
|
||||||
const before = (_a = event.data) === null || _a === void 0 ? void 0 : _a.before.data();
|
const before = (_a = event.data) === null || _a === void 0 ? void 0 : _a.before.data();
|
||||||
const after = (_b = event.data) === null || _b === void 0 ? void 0 : _b.after.data();
|
const after = (_b = event.data) === null || _b === void 0 ? void 0 : _b.after.data();
|
||||||
if (!isKeyGenerationIncrease(before === null || before === void 0 ? void 0 : before.keyGeneration, after === null || after === void 0 ? void 0 : after.keyGeneration))
|
const rotated = isKeyGenerationIncrease(before === null || before === void 0 ? void 0 : before.keyGeneration, after === null || after === void 0 ? void 0 : after.keyGeneration);
|
||||||
|
const phrasePublished = isPhrasePublished(before === null || before === void 0 ? void 0 : before.phraseGeneration, after === null || after === void 0 ? void 0 : after.phraseGeneration);
|
||||||
|
if (!rotated && !phrasePublished)
|
||||||
return;
|
return;
|
||||||
const { coupleId } = event.params;
|
const { coupleId } = event.params;
|
||||||
const db = admin.firestore();
|
const db = admin.firestore();
|
||||||
const userIds = ((_c = after === null || after === void 0 ? void 0 : after.userIds) !== null && _c !== void 0 ? _c : []);
|
const userIds = ((_c = after === null || after === void 0 ? void 0 : after.userIds) !== null && _c !== void 0 ? _c : []);
|
||||||
if (userIds.length === 0)
|
if (userIds.length === 0)
|
||||||
return;
|
return;
|
||||||
log_1.logger.log(`[onCoupleKeyRotated] couple=${coupleId} generation=${after === null || after === void 0 ? void 0 : after.keyGeneration}`);
|
// A rotation and a phrase publish are separate write shapes (the rules forbid combining them), so
|
||||||
|
// exactly one of these is true per event.
|
||||||
|
const alert = rotated
|
||||||
|
? {
|
||||||
|
type: 'couple_key_rotated',
|
||||||
|
title: '🔑 Security update',
|
||||||
|
body: 'Your shared key was rotated. Open the app and everything continues as normal.',
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
// Not merely informational: the change CANNOT complete until the partner's app opens and
|
||||||
|
// confirms it can read the new phrase. This push is what gets them there. And if they didn't
|
||||||
|
// expect a phrase change, this is how they find out — the was-this-you philosophy again.
|
||||||
|
type: 'recovery_phrase_changed',
|
||||||
|
title: '🔑 Security update',
|
||||||
|
body: 'Your recovery phrase was changed. Open the app to finish saving the new one.',
|
||||||
|
};
|
||||||
|
log_1.logger.log(`[onCoupleKeyRotated] couple=${coupleId} ` +
|
||||||
|
`${rotated ? `generation=${after === null || after === void 0 ? void 0 : after.keyGeneration}` : `phraseGeneration=${after === null || after === void 0 ? void 0 : after.phraseGeneration}`}`);
|
||||||
// Per-member isolation: one failed send must not cost the other member their alert.
|
// Per-member isolation: one failed send must not cost the other member their alert.
|
||||||
const results = await Promise.allSettled(userIds.map((uid) => (0, queueAndPush_1.queueAndPush)(db, uid, {
|
const results = await Promise.allSettled(userIds.map((uid) => (0, queueAndPush_1.queueAndPush)(db, uid, Object.assign(Object.assign({}, alert), { coupleId, bypassQuietHours: true }))));
|
||||||
type: 'couple_key_rotated',
|
|
||||||
title: '🔑 Security update',
|
|
||||||
body: 'Your shared key was rotated. Open the app and everything continues as normal.',
|
|
||||||
coupleId,
|
|
||||||
bypassQuietHours: true,
|
|
||||||
})));
|
|
||||||
results.forEach((r, i) => {
|
results.forEach((r, i) => {
|
||||||
if (r.status === 'rejected') {
|
if (r.status === 'rejected') {
|
||||||
log_1.logger.warn('[onCoupleKeyRotated] alert failed', { uid: userIds[i], error: String(r.reason) });
|
log_1.logger.warn('[onCoupleKeyRotated] alert failed', { uid: userIds[i], error: String(r.reason) });
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"onCoupleKeyRotated.js","sourceRoot":"","sources":["../../src/couples/onCoupleKeyRotated.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,0DAIC;AArBD,sDAAuC;AACvC,+DAAmE;AACnE,gEAA4D;AAC5D,gCAA+B;AAE/B;;;;;;;;;GASG;AAEH,qGAAqG;AACrG,SAAgB,uBAAuB,CAAC,MAAe,EAAE,KAAc;IACrE,MAAM,CAAC,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IACjD,MAAM,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/C,OAAO,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAEY,QAAA,kBAAkB,GAAG,IAAA,6BAAiB,EAAC,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;;IACxF,MAAM,MAAM,GAAG,MAAA,KAAK,CAAC,IAAI,0CAAE,MAAM,CAAC,IAAI,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,MAAA,KAAK,CAAC,IAAI,0CAAE,KAAK,CAAC,IAAI,EAAE,CAAA;IACtC,IAAI,CAAC,uBAAuB,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,aAAa,EAAE,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,aAAa,CAAC;QAAE,OAAM;IAEjF,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,CAAA;IACjC,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;IAC5B,MAAM,OAAO,GAAG,CAAC,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,mCAAI,EAAE,CAAa,CAAA;IAClD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAEhC,YAAM,CAAC,GAAG,CAAC,+BAA+B,QAAQ,eAAe,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,aAAa,EAAE,CAAC,CAAA;IAExF,oFAAoF;IACpF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAClB,IAAA,2BAAY,EAAC,EAAE,EAAE,GAAG,EAAE;QACpB,IAAI,EAAE,oBAAoB;QAC1B,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,+EAA+E;QACrF,QAAQ;QACR,gBAAgB,EAAE,IAAI;KACvB,CAAC,CACH,CACF,CAAA;IACD,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvB,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,YAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAChG,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
{"version":3,"file":"onCoupleKeyRotated.js","sourceRoot":"","sources":["../../src/couples/onCoupleKeyRotated.ts"],"names":[],"mappings":"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"}
|
||||||
|
|
@ -21,4 +21,21 @@ describe('isKeyGenerationIncrease', () => {
|
||||||
expect((0, onCoupleKeyRotated_1.isKeyGenerationIncrease)(null, 'high')).toBe(false);
|
expect((0, onCoupleKeyRotated_1.isKeyGenerationIncrease)(null, 'high')).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('isPhrasePublished', () => {
|
||||||
|
it('fires when a new recovery phrase is published (phase 1)', () => {
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(undefined, 1)).toBe(true);
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(0, 1)).toBe(true);
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(2, 3)).toBe(true);
|
||||||
|
});
|
||||||
|
it('ignores the acks and the completion — only the publish needs the partner in the app', () => {
|
||||||
|
// Phase 2 (acks) and phase 3 (the re-wrap) leave phraseGeneration alone, so they must not alert:
|
||||||
|
// the partner is already acting, and re-alerting them would be noise on a security channel.
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(1, 1)).toBe(false);
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(undefined, undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
it('never fires on a downgrade or a redelivered stale event', () => {
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(5, 4)).toBe(false);
|
||||||
|
expect((0, onCoupleKeyRotated_1.isPhrasePublished)(1, undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
//# sourceMappingURL=onCoupleKeyRotated.test.js.map
|
//# sourceMappingURL=onCoupleKeyRotated.test.js.map
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"onCoupleKeyRotated.test.js","sourceRoot":"","sources":["../../src/couples/onCoupleKeyRotated.test.ts"],"names":[],"mappings":";;AAAA,6DAA8D;AAE9D,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,IAAA,4CAAuB,EAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxD,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChD,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,uGAAuG;QACvG,MAAM,CAAC,IAAA,4CAAuB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjE,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mGAAmG,EAAE,GAAG,EAAE;QAC3G,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,IAAA,4CAAuB,EAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACrD,MAAM,CAAC,IAAA,4CAAuB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
{"version":3,"file":"onCoupleKeyRotated.test.js","sourceRoot":"","sources":["../../src/couples/onCoupleKeyRotated.test.ts"],"names":[],"mappings":";;AAAA,6DAAiF;AAEjF,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,IAAA,4CAAuB,EAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxD,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChD,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,uGAAuG;QACvG,MAAM,CAAC,IAAA,4CAAuB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjE,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mGAAmG,EAAE,GAAG,EAAE;QAC3G,MAAM,CAAC,IAAA,4CAAuB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,IAAA,4CAAuB,EAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACrD,MAAM,CAAC,IAAA,4CAAuB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,IAAA,sCAAiB,EAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClD,MAAM,CAAC,IAAA,sCAAiB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1C,MAAM,CAAC,IAAA,sCAAiB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,iGAAiG;QACjG,4FAA4F;QAC5F,MAAM,CAAC,IAAA,sCAAiB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3C,MAAM,CAAC,IAAA,sCAAiB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,IAAA,sCAAiB,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3C,MAAM,CAAC,IAAA,sCAAiB,EAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
||||||
Loading…
Reference in New Issue