Repository: flutter
Issue: Monorepo needs something like "visibility check"
Labels: team-infra,P2,triaged-infra,monorepo

One "benefit" of the current `flutter/flutter` and `flutter/engine` structure is that `flutter/flutter` can't depend on artifacts from `flutter/engine` that are not explicitly exported as part of the build, and `flutter/engine` can't depend on anything from `flutter/flutter` (at least not in a normal way). Of course, that is also a _downside_, for example `flutter/engine` regularly needs to reproduce working tools and infrastructure (Skia Gold, Scenario App, etc) that have working solutions in `flutter/flutter`.

_However_, we won't unconditionally want to share code and create a giant spaghetti ball of dependencies (imagine [`flutter/engine/tools`](https://github.com/flutter/engine/tree/main/tools) and [`flutter/flutter/dev`](https://github.com/flutter/flutter/tree/master/dev) getting mixed-up together), and wouldn't want the framework to start introspecting on and getting handles of non-artifacts from the engine that aren't explicitly meant to be public.

---

We will need _something_ like a visibility or access system. Some (not conclusive) options:

## Informal

At the very least, we should document what directories are expected to import what other directories.

That way:

- We have a source of truth on the intent, and can use it in code review or escalations
- There is a reference point if we want to improve tooling
- There is a place for folks to propose changes to the rules in an orderly manner

I imagine the rules being very broad at first, for example something like:

```md
<!-- v0 -->
- `engine/` cannot use or depend on anything outside of `engine/` other than PATH binaries (e.g. `flutter`)
- code outside of the `engine/` cannot use or depend on anything inside of `engine/`
```

In the future we might expand the rules post refactoring. For example:

```md
<!-- v1 -->
- `engine/` cannot use or depend on anything outside of `engine/` other than PATH binaries (e.g. `flutter`) but _can_ depend on Dart packages listed in `internal/common`
```

## Best Effort w/ Bot tooling

The next step would be to invest in some tooling that, as a best effort, enforce the rules above.

We would go after obvious cases, that is, likely just enforce `pubspec.yaml` dependencies (assuming that lints are in place that require all dependencies to be listed in pubspec, I believe they are). In other words, the following could still happen:

```dart
import 'dart:io' as io;

void main() {
  final naughtyFile = File('../engine/tools/file_i_want_to_read.txt');
}
```

## Best Effort w/ Bot tooling and CI prohibitions

We might decide it is impossibly difficult to encode all of the patterns and paths we want, or that we find that scripts keep making it into CI that reference files or directories they shouldn't, slowing down our progress. This might be technically difficult, but we could ensure that CI processes that run engine builds _literally_ do not have filesystem access to the framework folder, (or it's put in a random directory with only the `flutter` CLI working), and vica-versa for flutter/flutter and the engine.

I haven't thought too much about this, it's definitely possible - we'd want to exhaust other options first.

## Sandboxing

The most complete way to do this is to enforce build and test sandboxing, i.e. with _something like_:

<https://bazel.build/docs/sandboxing>

However, I'll leave that as out of scope at the moment.