feat(magic): inline enrollment in device card, remove preflight, align flag order
This commit is contained in:
parent
abeb1462f4
commit
c6035b97d9
1
.sixth/skills/ui-ux-pro-max
Submodule
1
.sixth/skills/ui-ux-pro-max
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit b7e3af80f6e331f6fb456667b82b12cade7c9d35
|
||||
@ -177,6 +177,89 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Inline enrollment panel -->
|
||||
<div
|
||||
v-if="enrollmentPhase !== 'idle'"
|
||||
class="mt-4 rounded-xl bg-indigo-50 dark:bg-indigo-900/20 border border-indigo-100 dark:border-indigo-800 p-4"
|
||||
>
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<UIcon
|
||||
name="i-heroicons-arrow-path"
|
||||
class="w-5 h-5 text-indigo-600 dark:text-indigo-400"
|
||||
:class="{ 'animate-spin': enrollmentPhase === 'loading' || enrollmentPhase === 'checking' }"
|
||||
/>
|
||||
<p class="text-sm font-bold text-indigo-900 dark:text-indigo-200">
|
||||
MDM-Enrollment
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Progress steps -->
|
||||
<div class="flex items-center gap-2 text-xs mb-4">
|
||||
<span
|
||||
class="px-2 py-1 rounded-full"
|
||||
:class="enrollmentPhase === 'loading' ? 'bg-indigo-200 text-indigo-800 dark:bg-indigo-700 dark:text-indigo-100' : 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'"
|
||||
>
|
||||
1. Profil laden
|
||||
</span>
|
||||
<span class="text-gray-400">→</span>
|
||||
<span
|
||||
class="px-2 py-1 rounded-full"
|
||||
:class="enrollmentPhase === 'waiting' ? 'bg-indigo-200 text-indigo-800 dark:bg-indigo-700 dark:text-indigo-100' : (enrollmentPhase === 'checking' || enrollmentPhase === 'success' || enrollmentPhase === 'error') ? 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300' : 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400'"
|
||||
>
|
||||
2. QR-Code scannen
|
||||
</span>
|
||||
<span class="text-gray-400">→</span>
|
||||
<span
|
||||
class="px-2 py-1 rounded-full"
|
||||
:class="enrollmentPhase === 'checking' ? 'bg-indigo-200 text-indigo-800 dark:bg-indigo-700 dark:text-indigo-100' : enrollmentPhase === 'success' ? 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300' : 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400'"
|
||||
>
|
||||
3. Prüfen
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- QR code -->
|
||||
<div v-if="enrollmentPhase === 'waiting' && enrollmentQrUrl" class="text-center space-y-3">
|
||||
<div class="bg-white p-3 rounded-xl inline-block">
|
||||
<img :src="enrollmentQrUrl" alt="Enrollment QR-Code" class="w-40 h-40">
|
||||
</div>
|
||||
<p class="text-xs text-indigo-700 dark:text-indigo-300">
|
||||
Scanne den Code mit der iPhone-Kamera und installiere das Profil.
|
||||
</p>
|
||||
<UButton
|
||||
size="sm"
|
||||
color="primary"
|
||||
:loading="enrollmentPhase === 'checking'"
|
||||
@click="checkInlineEnrollment"
|
||||
>
|
||||
Installation prüfen
|
||||
</UButton>
|
||||
</div>
|
||||
|
||||
<!-- Success / error -->
|
||||
<div v-if="enrollmentPhase === 'success'" class="text-sm text-green-700 dark:text-green-300">
|
||||
✓ Enrollment abgeschlossen. Das Gerät synchronisiert sich jetzt mit dem Backend.
|
||||
</div>
|
||||
<div v-if="enrollmentPhase === 'error'" class="text-sm text-red-700 dark:text-red-300">
|
||||
✗ {{ enrollmentError || "Enrollment fehlgeschlagen" }}
|
||||
</div>
|
||||
|
||||
<!-- Logs -->
|
||||
<div v-if="enrollmentLogs.length > 0" class="mt-3 text-xs bg-white/60 dark:bg-black/20 p-2 rounded overflow-auto max-h-32">
|
||||
<pre class="whitespace-pre-wrap">{{ enrollmentLogs.join('\n') }}</pre>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex justify-end">
|
||||
<UButton
|
||||
size="xs"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
@click="closeInlineEnrollment"
|
||||
>
|
||||
Schließen
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex items-center gap-3">
|
||||
<UButton
|
||||
v-if="action.to"
|
||||
@ -218,9 +301,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import QRCode from "qrcode";
|
||||
import type { ComputedDevice, DeviceStatus } from "~/composables/useDeviceStatus";
|
||||
import { useMdmStatus } from "~/composables/useMdmStatus";
|
||||
import { REBREAK_MDM_VERSION, getInstalledMdmVersion, type IphoneDeviceState } from "~/composables/useTauri";
|
||||
import { useTauri, REBREAK_MDM_VERSION, getInstalledMdmVersion, type IphoneDeviceState, type LocalServerInfo } from "~/composables/useTauri";
|
||||
|
||||
const props = defineProps<{
|
||||
device: ComputedDevice;
|
||||
@ -248,6 +332,20 @@ const manualSyncing = ref(false);
|
||||
const autoSyncing = ref(false);
|
||||
const autoSyncComplete = ref(false);
|
||||
|
||||
const {
|
||||
downloadAndPatchEnrollmentProfile,
|
||||
startLocalProfileServer,
|
||||
stopLocalProfileServer,
|
||||
getInstalledProfiles,
|
||||
mdmPush,
|
||||
} = useTauri();
|
||||
|
||||
const enrollmentPhase = ref<"idle" | "loading" | "waiting" | "checking" | "success" | "error">("idle");
|
||||
const enrollmentServerInfo = ref<LocalServerInfo | null>(null);
|
||||
const enrollmentQrUrl = ref<string>("");
|
||||
const enrollmentError = ref<string | null>(null);
|
||||
const enrollmentLogs = ref<string[]>([]);
|
||||
|
||||
const localEnrollment = computed(() =>
|
||||
props.iphone?.installedProfileIDs?.includes(ENROLLMENT_PROFILE_ID) ?? false,
|
||||
);
|
||||
@ -314,16 +412,16 @@ const localRows = computed(() => {
|
||||
const iphone = props.iphone;
|
||||
return [
|
||||
{
|
||||
label: "Supervised",
|
||||
value: iphone.isSupervised ? "Ja" : "Nein",
|
||||
valueClass: iphone.isSupervised
|
||||
label: "Enrollment",
|
||||
value: localEnrollment.value ? "Ja" : "Nein",
|
||||
valueClass: localEnrollment.value
|
||||
? "text-green-600 dark:text-green-400 font-medium"
|
||||
: "text-red-600 dark:text-red-400 font-medium",
|
||||
},
|
||||
{
|
||||
label: "Enrollment",
|
||||
value: localEnrollment.value ? "Ja" : "Nein",
|
||||
valueClass: localEnrollment.value
|
||||
label: "Supervised",
|
||||
value: iphone.isSupervised ? "Ja" : "Nein",
|
||||
valueClass: iphone.isSupervised
|
||||
? "text-green-600 dark:text-green-400 font-medium"
|
||||
: "text-red-600 dark:text-red-400 font-medium",
|
||||
},
|
||||
@ -479,6 +577,15 @@ const action = computed<IosAction>(() => {
|
||||
};
|
||||
}
|
||||
|
||||
if (enrollmentPhase.value !== "idle") {
|
||||
return {
|
||||
label: "Enrollment läuft…",
|
||||
icon: "i-heroicons-arrow-path",
|
||||
color: "neutral",
|
||||
variant: "soft",
|
||||
};
|
||||
}
|
||||
|
||||
if (!props.isConnected || !props.iphone) {
|
||||
return {
|
||||
label: "iPhone verbinden, um ReBreak Cloud zu synchronisieren",
|
||||
@ -512,12 +619,20 @@ const action = computed<IosAction>(() => {
|
||||
|
||||
if (!backend?.enrolled || !localEnrollment.value) {
|
||||
const isKnownDevice = !!props.device.mdmId;
|
||||
if (isKnownDevice) {
|
||||
return {
|
||||
label: isKnownDevice ? "Schutz vervollständigen" : "Enrollen",
|
||||
icon: isKnownDevice ? "i-heroicons-shield-check" : "i-heroicons-document-check",
|
||||
label: "Enrollment starten",
|
||||
icon: "i-heroicons-document-check",
|
||||
color: "primary",
|
||||
variant: "solid",
|
||||
to: isKnownDevice ? "/preflight" : "/enroll",
|
||||
};
|
||||
}
|
||||
return {
|
||||
label: "Enrollen",
|
||||
icon: "i-heroicons-document-check",
|
||||
color: "primary",
|
||||
variant: "solid",
|
||||
to: "/enroll",
|
||||
};
|
||||
}
|
||||
|
||||
@ -627,10 +742,86 @@ function onActionClick() {
|
||||
return;
|
||||
}
|
||||
|
||||
const backend = mdmState.value.data;
|
||||
if (props.device.mdmId && (!backend?.enrolled || !localEnrollment.value)) {
|
||||
startInlineEnrollment();
|
||||
return;
|
||||
}
|
||||
|
||||
manualSyncing.value = true;
|
||||
emit("sync", props.device);
|
||||
setTimeout(() => {
|
||||
manualSyncing.value = false;
|
||||
}, 800);
|
||||
}
|
||||
|
||||
async function startInlineEnrollment() {
|
||||
if (!props.iphone?.udid) return;
|
||||
|
||||
enrollmentPhase.value = "loading";
|
||||
enrollmentError.value = null;
|
||||
enrollmentLogs.value = [];
|
||||
enrollmentQrUrl.value = "";
|
||||
enrollmentServerInfo.value = null;
|
||||
|
||||
try {
|
||||
const url = "https://mdm.rebreak.org/enrollment/rebreak-enrollment.mobileconfig";
|
||||
enrollmentLogs.value.push(`→ Lade Enrollment-Profil`);
|
||||
const path = await downloadAndPatchEnrollmentProfile(url, props.iphone.udid);
|
||||
enrollmentLogs.value.push(`✓ Profil gespeichert`);
|
||||
|
||||
enrollmentServerInfo.value = await startLocalProfileServer(path);
|
||||
enrollmentLogs.value.push(`✓ Lokaler Server gestartet`);
|
||||
|
||||
enrollmentQrUrl.value = await QRCode.toDataURL(enrollmentServerInfo.value.qr_payload, {
|
||||
width: 192,
|
||||
margin: 2,
|
||||
});
|
||||
|
||||
enrollmentPhase.value = "waiting";
|
||||
} catch (e: any) {
|
||||
enrollmentError.value = e?.message ?? "Enrollment konnte nicht gestartet werden";
|
||||
enrollmentLogs.value.push(`✗ ${enrollmentError.value}`);
|
||||
enrollmentPhase.value = "error";
|
||||
}
|
||||
}
|
||||
|
||||
async function checkInlineEnrollment() {
|
||||
if (!props.iphone?.udid) return;
|
||||
|
||||
enrollmentPhase.value = "checking";
|
||||
enrollmentError.value = null;
|
||||
|
||||
try {
|
||||
const ids = await getInstalledProfiles();
|
||||
if (props.iphone) {
|
||||
props.iphone.installedProfileIDs = ids;
|
||||
}
|
||||
|
||||
if (!ids.includes(ENROLLMENT_PROFILE_ID)) {
|
||||
enrollmentError.value = "Enrollment-Profil noch nicht installiert. Bitte QR-Code scannen und Profil installieren.";
|
||||
enrollmentPhase.value = "error";
|
||||
return;
|
||||
}
|
||||
|
||||
enrollmentLogs.value.push("✓ Enrollment-Profil erkannt");
|
||||
const push = await mdmPush(props.iphone.udid);
|
||||
enrollmentLogs.value.push(`✓ Push: ${push.push_result}`);
|
||||
|
||||
await refreshMdmStatus();
|
||||
enrollmentPhase.value = "success";
|
||||
} catch (e: any) {
|
||||
enrollmentError.value = e?.message ?? "Prüfung fehlgeschlagen";
|
||||
enrollmentLogs.value.push(`✗ ${enrollmentError.value}`);
|
||||
enrollmentPhase.value = "error";
|
||||
}
|
||||
}
|
||||
|
||||
function closeInlineEnrollment() {
|
||||
stopLocalProfileServer();
|
||||
enrollmentPhase.value = "idle";
|
||||
enrollmentServerInfo.value = null;
|
||||
enrollmentQrUrl.value = "";
|
||||
enrollmentError.value = null;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
<template>
|
||||
<button
|
||||
class="w-full text-left"
|
||||
@click="toggle"
|
||||
>
|
||||
<div
|
||||
class="flex items-start gap-3 p-4 rounded-xl transition-colors"
|
||||
:class="checked || auto ? 'bg-green-50/50 ring-1 ring-green-100' : 'bg-gray-50 hover:bg-gray-100'"
|
||||
>
|
||||
<UIcon
|
||||
:name="checked || auto ? 'i-heroicons-check-circle-solid' : 'i-heroicons-circle'"
|
||||
class="w-6 h-6 shrink-0"
|
||||
:class="checked || auto ? 'text-green-600' : 'text-gray-400'"
|
||||
/>
|
||||
<div>
|
||||
<div class="font-bold text-gray-900">{{ title }}</div>
|
||||
<div class="text-sm text-gray-500 mt-0.5">{{ detail }}</div>
|
||||
<div v-if="auto && !checked" class="text-xs text-green-600 font-semibold mt-1">
|
||||
Automatisch erkannt ✓
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
modelValue: boolean;
|
||||
title: string;
|
||||
detail: string;
|
||||
auto?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:modelValue", value: boolean): void;
|
||||
}>();
|
||||
|
||||
const checked = computed(() => props.modelValue || props.auto);
|
||||
|
||||
function toggle() {
|
||||
emit("update:modelValue", !props.modelValue);
|
||||
}
|
||||
</script>
|
||||
@ -97,7 +97,7 @@
|
||||
Zurück
|
||||
</UButton>
|
||||
<UButton
|
||||
to="/preflight"
|
||||
to="/supervise"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
:disabled="!iphone"
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<div class="min-h-screen flex flex-col items-center justify-center bg-gray-50 p-6">
|
||||
<div class="max-w-md w-full space-y-6">
|
||||
<div class="text-center">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Pre-Flight Check</h1>
|
||||
<p class="text-gray-600 mt-2">
|
||||
Bevor wir dein iPhone supervisieren, müssen ein paar Apple-Sicherheitschecks erledigt sein.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<UCard>
|
||||
<div class="space-y-3">
|
||||
<PreflightItem
|
||||
v-model="checks.fmi"
|
||||
title="Find My iPhone deaktiviert"
|
||||
detail="Settings → [Apple-ID] → Wo ist? → Mein iPhone suchen → AUS. Ohne das blockiert Apple das Supervisieren."
|
||||
:auto="iphone?.findMyEnabled === false"
|
||||
/>
|
||||
<PreflightItem
|
||||
v-model="checks.sdp"
|
||||
title="Stolen Device Protection ausgeschaltet"
|
||||
detail="Settings → Face ID & Code → Schutz für gestohlene Geräte → AUS. SDP zwingt FMI an."
|
||||
/>
|
||||
<PreflightItem
|
||||
v-model="checks.appleId"
|
||||
title="Apple-ID-Passwort griffbereit"
|
||||
detail="Apple fragt evtl. dein Apple-ID-PW während des FMI-Toggles ab."
|
||||
/>
|
||||
<PreflightItem
|
||||
v-model="checks.appInstalled"
|
||||
title="ReBreak-App ist auf dem iPhone installiert"
|
||||
detail="Über TestFlight. Erst danach kann der Wizard die App in den Managed-State versetzen."
|
||||
:auto="hasReBreakApp"
|
||||
/>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<UButton to="/detect" variant="ghost" color="neutral">
|
||||
Zurück
|
||||
</UButton>
|
||||
<UButton
|
||||
to="/supervise"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
:disabled="!allChecked"
|
||||
>
|
||||
Supervisieren starten →
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { useIphoneDevice } from "~/composables/useMagicState";
|
||||
import PreflightItem from "~/components/PreflightItem.vue";
|
||||
|
||||
const iphone = useIphoneDevice();
|
||||
|
||||
const checks = ref({
|
||||
fmi: false,
|
||||
sdp: false,
|
||||
appleId: false,
|
||||
appInstalled: false,
|
||||
});
|
||||
|
||||
const hasReBreakApp = computed(() =>
|
||||
iphone.value?.installedAppBundleIDs?.includes("org.rebreak.app") ?? false,
|
||||
);
|
||||
|
||||
const allChecked = computed(() =>
|
||||
(checks.value.fmi || iphone.value?.findMyEnabled === false) &&
|
||||
checks.value.sdp &&
|
||||
checks.value.appleId &&
|
||||
(checks.value.appInstalled || hasReBreakApp.value),
|
||||
);
|
||||
</script>
|
||||
@ -54,7 +54,7 @@
|
||||
</UCard>
|
||||
|
||||
<div class="flex justify-between">
|
||||
<UButton to="/preflight" variant="ghost" color="neutral">
|
||||
<UButton to="/" variant="ghost" color="neutral">
|
||||
Zurück
|
||||
</UButton>
|
||||
<UButton
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Graph Report - rebreak-monorepo (2026-06-18)
|
||||
|
||||
## Corpus Check
|
||||
- 1526 files · ~1,868,068 words
|
||||
- 1526 files · ~1,868,054 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
@ -10,7 +10,7 @@
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `0efdf2f8`
|
||||
- Built from commit: `709f8cb3`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
@ -5700,11 +5700,11 @@ Nodes (3): ShellScopeEntryAllowedArgs, anyOf, description
|
||||
_Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `Notification` connect `Community 93` to `Debug & Dev Tools`, `Community 39`, `i18n: Pricing Strings`, `i18n: Pricing Strings`, `Community 181`, `Community 53`?**
|
||||
_High betweenness centrality (0.032) - this node is a cross-community bridge._
|
||||
_High betweenness centrality (0.038) - this node is a cross-community bridge._
|
||||
- **Why does `useColors()` connect `Community 53` to `Backend API Routes`, `Community 1030`, `Consent & Magic API Routes`, `i18n: Pricing Strings`, `App Root Layout & Shell`, `Community 18`, `Community 20`, `Community 21`, `Community 22`, `Community 27`, `Community 413`, `Community 34`, `Community 37`, `Community 426`, `Community 686`, `Community 437`, `Community 54`, `Community 80`, `Community 93`, `Community 95`, `Community 865`, `Community 872`, `Community 616`?**
|
||||
_High betweenness centrality (0.032) - this node is a cross-community bridge._
|
||||
- **Why does `usePrisma()` connect `Debug & Dev Tools` to `Community 384`, `Community 257`, `Community 385`, `Backend API Routes`, `Backend Tests & Auth Routes`, `Android DNS Filter (Kotlin)`, `Community 32`, `Community 33`, `Community 39`, `Community 937`, `Community 47`, `Community 181`, `Community 566`, `Community 62`, `Community 68`, `Community 69`, `Community 80`, `Community 93`, `Community 244`, `Community 127`?**
|
||||
_High betweenness centrality (0.025) - this node is a cross-community bridge._
|
||||
_High betweenness centrality (0.036) - this node is a cross-community bridge._
|
||||
- **Why does `Error` connect `Community 396` to `Community 290`, `Community 355`, `Community 419`, `Community 67`, `Community 263`, `Community 74`, `Community 876`, `Community 109`, `Community 81`, `Community 883`, `Community 212`, `Community 213`, `Community 117`, `Community 438`, `Community 122`, `Community 254`, `Community 607`?**
|
||||
_High betweenness centrality (0.031) - this node is a cross-community bridge._
|
||||
- **Are the 2 inferred relationships involving `usePrisma()` (e.g. with `runRevoke()` and `requireUser()`) actually correct?**
|
||||
_`usePrisma()` has 2 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **What connects `deviceIdRef`, `{ state: mdmState, refresh: refreshMdmStatus }`, `manualSyncing` to the rest of the system?**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -8470,8 +8470,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/components/IosDeviceCard.vue": {
|
||||
"mtime": 1781756877.0845668,
|
||||
"ast_hash": "6d8059a60590b33fc238b2d3012cb3ee",
|
||||
"mtime": 1781760166.407032,
|
||||
"ast_hash": "594b640f925dd262380a953908ec2e53",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/components/IosDeviceSection.vue": {
|
||||
@ -9070,8 +9070,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/backend/server/api/magic/devices/[deviceId]/mdm.get.ts": {
|
||||
"mtime": 1781758009.6469717,
|
||||
"ast_hash": "b0a1b76bdc305c925326f6787aebbe11",
|
||||
"mtime": 1781759183.6660445,
|
||||
"ast_hash": "e1c779f82c164aaf5dfe1b55f6f0eaca",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/backend/server/api/magic/devices/[deviceId]/mdm-link.post.ts": {
|
||||
@ -9134,11 +9134,6 @@
|
||||
"ast_hash": "793e67cb3bfa5b6eaac5b50c74cde28b",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/components/PreflightItem.vue": {
|
||||
"mtime": 1781729471.357726,
|
||||
"ast_hash": "654d7bdac2f3c7e4909a13ee00ac3c37",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/components/StepButton.vue": {
|
||||
"mtime": 1781729471.3821392,
|
||||
"ast_hash": "5ff0e5638aa149c647921ab6687b5ea8",
|
||||
@ -9160,8 +9155,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/pages/detect.vue": {
|
||||
"mtime": 1781729471.4505167,
|
||||
"ast_hash": "70c0a0b1b507a92cfb06e0c980b23b8f",
|
||||
"mtime": 1781759990.788815,
|
||||
"ast_hash": "eee90e00189e22dd8c99eccf5b7598a5",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/pages/desktop-enroll.vue": {
|
||||
@ -9189,14 +9184,9 @@
|
||||
"ast_hash": "19f47d384164a9f9e4cceacd3161e5c0",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/pages/preflight.vue": {
|
||||
"mtime": 1781729471.51261,
|
||||
"ast_hash": "8cbd20d4fcc93d5228d6ac58bfca2c89",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/app/pages/supervise.vue": {
|
||||
"mtime": 1781729471.5354013,
|
||||
"ast_hash": "113ce0ab42e4e160b3276e008f99a913",
|
||||
"mtime": 1781759990.7880056,
|
||||
"ast_hash": "e00cf0b40d94df6eb80dfec34ff1b323",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-magic/src-tauri/tauri.conf.json": {
|
||||
@ -9338,5 +9328,10 @@
|
||||
"mtime": 1781748641.7178783,
|
||||
"ast_hash": "22842b3019c2bb3175d475e92b437109",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"/Users/chahinebrini/mono/rebreak-monorepo/.woodpecker.yml": {
|
||||
"mtime": 1781760270.0506988,
|
||||
"ast_hash": "52e575610d792dfc647b067ecdb518b5",
|
||||
"semantic_hash": ""
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user