Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
62f2257
App ID saved and printed
sharon-fdm Feb 21, 2026
bec9efc
enroll
sharon-fdm Feb 21, 2026
38fe5cd
debug files
sharon-fdm Feb 21, 2026
e5068e0
final
sharon-fdm Feb 21, 2026
717cd55
checkin every 15 sec
sharon-fdm Feb 22, 2026
8d43264
print the queries only
sharon-fdm Feb 22, 2026
cc6a958
working osquery
sharon-fdm Feb 22, 2026
a817b6e
add logcat table
sharon-fdm Feb 22, 2026
0dfe6f1
fix
sharon-fdm Feb 22, 2026
bc0cf82
docs(schema): add Android table schemas for osquery tables pages
sharon-fdm Mar 13, 2026
ed4323e
Merge remote-tracking branch 'origin/main' into step4-improvements
sharon-fdm Mar 13, 2026
c8608bd
docs(android): rename README to Osquery on Android intro
sharon-fdm Mar 13, 2026
3d1db52
docs(android): add concise enrollment flow summary
sharon-fdm Mar 13, 2026
22e8847
docs(android): keep original README and append osquery-on-android sec…
sharon-fdm Mar 13, 2026
28938c8
docs(android): add query polling cadence summary
sharon-fdm Mar 13, 2026
e5bb88a
docs(android): add markdown reference for Android osquery tables
sharon-fdm Mar 13, 2026
32bc689
docs(android): expand osquery-on-android guide and operations sections
sharon-fdm Mar 13, 2026
13fb3cf
docs(android): condense table reference into compact summary format
sharon-fdm Mar 13, 2026
9840cbf
security(android-osquery): harden transport, logging, and logcat table
sharon-fdm Mar 13, 2026
03add8f
security(android-osquery): harden enrollment URL validation and tests
sharon-fdm Mar 13, 2026
fb1db32
docs(android): add human-readable behavior contract and oracle
sharon-fdm Mar 13, 2026
38f9798
docs(android): clarify AI provenance and human-readable oracle rules
sharon-fdm Mar 13, 2026
d3d2600
docs(android): add contract/oracle compliance statement
sharon-fdm Mar 13, 2026
86e69bc
docs(android): clarify AI performed manual validation
sharon-fdm Mar 13, 2026
f00793b
docs(android): add top-level AI-generated provenance note
sharon-fdm Mar 13, 2026
1106ccb
docs(android): unify contract/oracle and add mixed provenance note
sharon-fdm Mar 13, 2026
e89365c
feat(android-osquery): add cross-OS time and uptime tables
sharon-fdm Mar 13, 2026
4da7e86
docs(android): propose team-wide contract-first AI workflow (P2/O8)
sharon-fdm Mar 13, 2026
58ce035
docs(android): add reusable contract-first AI workflow instruction file
sharon-fdm Mar 13, 2026
1a30d96
feat(android-osquery): add system_info kernel_info memory_info tables…
sharon-fdm Mar 14, 2026
84be47a
docs(android): mark contract/oracle coverage through C10 and O11
sharon-fdm Mar 14, 2026
c45fd70
docs(android): simplify contract/oracle to ordered core spec
sharon-fdm Mar 14, 2026
7f95959
security(android): harden distributed path, manifest, and security co…
sharon-fdm Mar 14, 2026
96f7a4d
docs(android): add comprehensive android osquery test plan
sharon-fdm Mar 14, 2026
2094e8c
feat(android-osquery): add processes network and system parity tables…
sharon-fdm Mar 14, 2026
575a6ec
feat(android-osquery): add app_signatures mdm_status startup_items ta…
sharon-fdm Mar 14, 2026
b91f8c2
test(android): add negative security-path tests and expand test plan …
sharon-fdm Mar 14, 2026
b8e2cc1
docs(android): add quality-evidence contract/oracle requirements (C14…
sharon-fdm Mar 14, 2026
cd0a938
docs(android): add high-level enrollment scenario to contract
sharon-fdm Mar 14, 2026
49a91bf
Merge remote-tracking branch 'origin/main' into step4-improvements
sharon-fdm Mar 14, 2026
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
400 changes: 400 additions & 0 deletions android/000_BEHAVIOR_CONTRACT_AND_ORACLE.md

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions android/000_PASTE_INTO_AI_TERMINAL_CONTRACT_ORACLE_WORKFLOW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Contract-First AI Workflow (Paste Into Codex/Claude)

Use this instruction at the start of every AI coding session.

## Mission
Work in a **contract-first** way.
Before changing code, create a clear behavior contract and oracle, get human approval, and only then implement.

## Core concepts (required)
- **Behavior contract**:
The human-readable description of what the system must do and what must remain true.
It defines boundaries, invariants, and expected behavior.
- **Oracle**:
The concrete, observable checks that decide whether implementation behavior is acceptable.
Oracles can be unit tests, integration tests, runtime checks, logs, and manual validation steps.

## Mandatory workflow for every request
1. Restate human intent in 1-3 clear lines.
2. Propose contract changes first.
3. Propose oracle changes first.
4. Ask for human approval.
5. Stop. Do not edit implementation code before explicit approval.
6. After approval, implement exactly according to the approved contract/oracle.
7. Run verification and map results to oracle items.
8. Report what is tested vs not tested.

## Required behavior rules
- Always produce a contract/oracle delta before code changes.
- Always request a clear approval checkpoint before implementation.
- Keep contract/oracle human-readable, short, and reviewable.
- If a requirement is ambiguous, ask a clarifying question before implementation.

## Truthfulness and provenance rules
- Never claim “contract came first” when it did not.
- If contract was extracted from existing code, state that explicitly.
- If part was contract-first and part was reverse-extracted, state both clearly.
- Separate confidence from proof:
- acceptable: “appears compliant based on tests/manual validation”
- not acceptable: “proven correct” unless formal proof exists.
- If manual validation was performed by AI, say so explicitly.

## Oracle quality rules
Each oracle section must include:
- `Human rule`: plain-language expected behavior.
- `How to verify`: exact checks (test command, query, runtime check, etc.).
- `Coverage status`: tested / not tested.

Prefer deterministic checks and avoid vague acceptance criteria.

## PR reporting rules
In PR description (or equivalent summary), include:
- Link to contract/oracle file.
- Short `Tested` section mapped to oracle IDs.
- Short `Not tested` section mapped to oracle IDs.

## Output style
- Be concise and direct.
- Use simple language.
- Optimize for human review speed.

## Start behavior (important)
After receiving this instruction, your first action on any new task is:
1. Draft contract/oracle changes.
2. Ask for review/approval.
3. Wait.
256 changes: 256 additions & 0 deletions android/001_TEST_PLAN_ANDROID_OSQUERY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
# Android Osquery Test Plan

## Purpose
Provide a practical, repeatable test plan for validating Android osquery behavior, enrollment reliability, and security controls before merge/release.

## Scope
This plan covers:
- Enrollment and re-enrollment behavior
- Distributed query read/execute/write loop
- SQL surface and table behavior
- Security controls in enrollment/distributed paths
- Real-device validation and regression checks

Out of scope:
- Full certificate/SCEP matrix (covered by dedicated certificate tests)
- Non-Android platforms

## Reference contract/oracle
- Contract + oracle: `android/000_BEHAVIOR_CONTRACT_AND_ORACLE.md`
- Key mappings used in this plan:
- Enrollment/transport: O1, O2
- Distributed loop: O3, O4
- Table oracles: O5, O6, O7, O9, O10, O11
- Security baseline: O12

## Test environments
- Local dev:
- macOS + Android SDK + JDK 17+
- Fleet server reachable at localhost/LAN
- Android device connected by ADB
- CI/local unit:
- JVM tests via Gradle
- Real device matrix (manual):
- At least 2 Android versions
- At least 2 OEMs if possible

## Entry criteria
- Branch builds locally
- Contract/oracle updated and reviewed
- Test device enrolled or ready to enroll

## Exit criteria
- All P0/P1 tests pass
- No open high-severity security issues
- Known minor risks documented in contract and PR QA

## Priority levels
- P0: Must pass for merge
- P1: Should pass before review sign-off
- P2: Nice-to-have confidence expansion

## Automated test suite (P0)

### A1. Enrollment + URL hardening
Command:
```bash
./gradlew :app:testDebugUnitTest --tests com.fleetdm.agent.ApiClientReenrollTest --console=plain --no-daemon
```
Expected:
- Re-enrollment on 401 works
- Non-401 does not re-enroll
- Identity change clears node key
- URL validation rules enforced

### A2. Time/uptime table oracle checks
Command:
```bash
./gradlew :app:testDebugUnitTest --tests com.fleetdm.agent.osquery.TimeAndUptimeTableTest --console=plain --no-daemon
```
Expected:
- `time` and `uptime` return one row
- numeric/time sanity checks pass

### A3. System/kernel/memory table oracle checks
Command:
```bash
./gradlew :app:testDebugUnitTest --tests com.fleetdm.agent.osquery.SystemKernelMemoryTableTest --console=plain --no-daemon
```
Expected:
- `system_info`, `kernel_info`, `memory_info` one-row shape and value parseability checks pass

### A4. Combined gate
Command:
```bash
./gradlew :app:compileDebugKotlin :app:testDebugUnitTest \
--tests com.fleetdm.agent.ApiClientReenrollTest \
--tests com.fleetdm.agent.osquery.TimeAndUptimeTableTest \
--tests com.fleetdm.agent.osquery.SystemKernelMemoryTableTest \
--tests com.fleetdm.agent.osquery.AdditionalParityTablesTest \
--tests com.fleetdm.agent.osquery.ManagementVisibilityTablesTest \
--console=plain --no-daemon
```
Expected:
- Full targeted suite passes

## Manual end-to-end validation (P0/P1)

### M1. Device enrollment smoke (P0)
Steps:
1. Confirm device:
```bash
adb devices
```
2. Reverse localhost:
```bash
adb reverse tcp:8080 tcp:8080
```
3. Install debug app:
```bash
FLEET_SERVER_URL='http://127.0.0.1:8080' ./gradlew installDebug
```
4. Reset app state and launch:
```bash
adb shell pm clear com.fleetdm.agent
adb shell monkey -p com.fleetdm.agent -c android.intent.category.LAUNCHER 1
```
Expected:
- Host appears in Fleet within expected check-in window

### M2. Distributed query loop smoke (P0)
Run in Fleet Live Query:
```sql
SELECT name, version, platform, security_patch FROM os_version;
```
Expected:
- Result returns from Android host
- No repeated stuck query behavior

### M3. Cross-OS table smoke (P1)
Run in Fleet Live Query:
```sql
SELECT * FROM time;
SELECT * FROM uptime;
SELECT * FROM system_info;
SELECT * FROM kernel_info;
SELECT * FROM memory_info;
SELECT * FROM processes LIMIT 20;
SELECT * FROM interface_addresses LIMIT 20;
SELECT * FROM routes LIMIT 20;
SELECT * FROM users;
SELECT * FROM mounts LIMIT 20;
SELECT * FROM cpu_info;
SELECT * FROM app_signatures LIMIT 20;
SELECT * FROM mdm_status;
SELECT * FROM startup_items LIMIT 20;
```
Expected:
- Exactly one row per table
- Key sanity:
- `time.unix_time` close to current epoch
- `uptime.total_seconds >= 0`
- `system_info.uuid` non-empty
- `kernel_info.platform='android'`
- memory numeric fields non-negative
- `users.uid` parseable and non-negative
- `cpu_info.cores` parseable and non-negative
- `mdm_status` boolean fields are parseable as `0`/`1`

### M4. Logcat table gating (P1)
1. Query with flag OFF:
```sql
SELECT * FROM android_logcat LIMIT 20;
```
Expected:
- Empty result
2. Enable managed config `enable_android_logcat_table=true` and retry.
Expected:
- Filtered Fleet-tag rows, no obvious secret leakage

## Security-focused tests (P0/P1)

### S1. URL policy (P0)
Verify behavior from automated tests (A1) and code paths:
- Non-debug requires HTTPS
- Reject path/query/fragment/userinfo in base URL

### S1b. Negative URL/config path (P0)
Command:
```bash
./gradlew :app:testDebugUnitTest --tests com.fleetdm.agent.SecurityNegativePathsTest --console=plain --no-daemon
```
Expected:
- Missing enrollment config fails closed (`Credentials not set`)

### S2. Re-enrollment control (P0)
Simulate/validate:
- 401 -> clear key -> re-enroll -> retry
- non-401 -> no re-enroll

### S3. Manifest security controls (P0)
Verify in manifest:
- `android:allowBackup="false"`
- `BootReceiver` exported false

### S4. Distributed path hardening (P0)
Code verification:
- `FleetDistributedQueryRunner` uses `ApiClient.distributedRead/distributedWrite`
- no custom unsafe TLS bypass path in active distributed loop

### S5. Identifier logging control (P1)
Release-like behavior:
- full Device ID not logged in non-debug

### S6. Accepted minor risk verification (P2)
- Enrollment secret currently in app-private DataStore (not Keystore-encrypted)
- Confirm risk remains documented in contract + PR QA

### S7. Negative SQL parser path (P1)
Command:
```bash
./gradlew :app:testDebugUnitTest --tests com.fleetdm.agent.SecurityNegativePathsTest --console=plain --no-daemon
```
Expected:
- Malformed SQL is rejected and does not crash worker/query engine path

## Lifecycle and corner-case tests (P1/P2)

### L1. Host delete + re-enroll (P1)
Flow:
1. Enroll device
2. Delete host in Fleet UI
3. Trigger next check-in
Expected:
- 401 path re-enrolls and host recovers

### L2. App uninstall/reinstall (P1)
Expected:
- Fresh enroll works, no stale-key failure

### L3. Work profile reset (P2)
Expected:
- Re-enrollment and query loop recover after profile recreation

### L4. Network disruption (P2)
Cases:
- captive portal
- intermittent connectivity
- TLS interception/proxy
Expected:
- Failures are controlled, no crash loops, recovery when network normalizes

## Test reporting template
For each run, record:
- Build/commit
- Device model + Android version
- Tests run (IDs)
- Result: pass/fail
- Evidence: command output, screenshot, query result, log snippet
- Follow-ups/issues

## Recommended merge gate
Minimum for merge:
- A4 pass
- M1 + M2 pass on at least one real device
- S1/S2/S3/S4 pass
- Open issues triaged, high severity resolved
Loading
Loading